From b2848064f46e7f38b07d54e65bc29f4702a9abe2 Mon Sep 17 00:00:00 2001 From: dwells-eit Date: Mon, 5 Jan 2026 12:03:49 +0000 Subject: [PATCH 1/4] Write autocycler post assembly subworkflow --- .../fasta_consensus_autocycler/main.nf | 94 +++++++++++++++++++ .../fasta_consensus_autocycler/meta.yml | 44 +++++++++ .../tests/main.nf.test | 44 +++++++++ 3 files changed, 182 insertions(+) create mode 100644 subworkflows/nf-core/fasta_consensus_autocycler/main.nf create mode 100644 subworkflows/nf-core/fasta_consensus_autocycler/meta.yml create mode 100644 subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/main.nf b/subworkflows/nf-core/fasta_consensus_autocycler/main.nf new file mode 100644 index 00000000000..0a4bcb5f732 --- /dev/null +++ b/subworkflows/nf-core/fasta_consensus_autocycler/main.nf @@ -0,0 +1,94 @@ + +include { AUTOCYCLER_COMPRESS } from '../../../modules/nf-core/autocycler/compress/main' +include { AUTOCYCLER_CLUSTER } from '../../../modules/nf-core/autocycler/cluster/main' +include { AUTOCYCLER_TRIM } from '../../../modules/nf-core/autocycler/trim/main' +include { AUTOCYCLER_RESOLVE } from '../../../modules/nf-core/autocycler/resolve/main' +include { AUTOCYCLER_COMBINE } from '../../../modules/nf-core/autocycler/combine/main' + +workflow FASTA_CONSENSUS_AUTOCYCLER { + + take: + ch_grouped_contigs // channel: [ val(meta), [ fasta, fasta, ... ] ] + + main: + + ch_versions = Channel.empty() + + AUTOCYCLER_COMPRESS ( + ch_grouped_contigs + ) + ch_versions = ch_versions.mix(AUTOCYCLER_COMPRESS.out.versions.first()) + + AUTOCYCLER_CLUSTER ( + AUTOCYCLER_COMPRESS.out.gfa + ) + ch_versions = ch_versions.mix(AUTOCYCLER_CLUSTER.out.versions.first()) + + AUTOCYCLER_CLUSTER.out.clusters + .flatMap { meta, gfa_list -> + ( gfa_list instanceof List ? gfa_list: [gfa_list] ) + .collect { gfa -> [meta, gfa] } // Separate gfas, each with a meta + } + .map { meta, file -> + def cluster_id = (file.parent.name) // Add cluster id to meta + tuple( meta + [cluster: cluster_id], file ) + } + .set{ ch_clusters } // channel: [ val(meta), gfa] + + AUTOCYCLER_TRIM( + ch_clusters + ) + ch_versions = ch_versions.mix(AUTOCYCLER_TRIM.out.versions.first()) + + AUTOCYCLER_RESOLVE( + AUTOCYCLER_TRIM.out.gfa + ) + ch_versions = ch_versions.mix(AUTOCYCLER_RESOLVE.out.versions.first()) + + // Rename resolved gfa files to include cluster ID and avoid filename collisions + RENAME( + AUTOCYCLER_RESOLVE.out.resolved, + AUTOCYCLER_RESOLVE.out.resolved.map{meta, file -> "${meta.id}_${meta.cluster}"} + ) + + // Group clusters based on meta, ignoring cluster id + RENAME.out.renamed + .map{ meta, file -> + def new_meta = meta.clone() + new_meta.remove("cluster") + tuple( new_meta, file) + } + .groupTuple() + .set{ ch_assembly_clusters } // channel: [ meta, [ cluster1, cluster2, ... ] ] + + AUTOCYCLER_COMBINE( + ch_assembly_clusters + ) + ch_versions = ch_versions.mix(AUTOCYCLER_COMBINE.out.versions.first()) + + ch_consensus_assembly = AUTOCYCLER_COMBINE.out.fasta // channel: [ val(meta), fasta ] + ch_consensus_assembly_graph = AUTOCYCLER_COMBINE.out.gfa // channel: [ val(meta), gfa ] + + + emit: + consensus_assembly = ch_consensus_assembly // channel: [ val(meta), fasta ] + consensus_assembly_graph = ch_consensus_assembly_graph // channel: [ val(meta), gfa ] + + versions = ch_versions // channel: [ versions.yml ] +} + +process RENAME { + tag "$meta.id" + + input: + tuple val(meta), path(file) + val key + + output: + tuple val(meta), path("${key}_${file}"), emit: renamed + + script: + """ + ln -s ${file} "${key}_${file}" + """ +} diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/meta.yml b/subworkflows/nf-core/fasta_consensus_autocycler/meta.yml new file mode 100644 index 00000000000..2aadbd5f6b2 --- /dev/null +++ b/subworkflows/nf-core/fasta_consensus_autocycler/meta.yml @@ -0,0 +1,44 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "fasta_consensus_autocycler" +description: Generate consensus assemblies and assembly graphs from grouped contig FASTA files using autocycler +keywords: + - autocycler + - consensus + - assembly + - fasta +components: + - autocycler/compress + - autocycler/cluster + - autocycler/trim + - autocycler/resolve + - autocycler/combine +input: + - ch_grouped_contigs: + type: file + description: | + The input channel containing grouped contig FASTA files + Structure: [ val(meta), [ fasta, fasta, ... ] ] + pattern: "*.{fasta,fa,fna}" +output: + - consensus_assembly: + type: file + description: | + Channel containing consensus assembly FASTA files + Structure: [ val(meta), path(fasta) ] + pattern: "*/consensus_assembly.fasta" + - consensus_assembly_graph: + type: file + description: | + Channel containing consensus assembly graphs + Structure: [ val(meta), path(gfa) ] + pattern: "*/consensus_assembly.gfa" + - versions: + type: file + description: | + File containing software versions + Structure: [ path(versions.yml) ] + pattern: "versions.yml" +authors: + - "@dwells-eit" +maintainers: + - "@dwells-eit" diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test new file mode 100644 index 00000000000..d5fa27f5667 --- /dev/null +++ b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test @@ -0,0 +1,44 @@ +// TODO nf-core: Once you have added the required tests, please run the following command to build this file: +// nf-core subworkflows test fasta_consensus_autocycler +nextflow_workflow { + + name "Test Subworkflow FASTA_CONSENSUS_AUTOCYCLER" + script "../main.nf" + workflow "FASTA_CONSENSUS_AUTOCYCLER" + + tag "subworkflows" + tag "subworkflows_nfcore" + tag "subworkflows/fasta_consensus_autocycler" + // TODO nf-core: Add tags for all modules used within this subworkflow. Example: + tag "samtools" + tag "samtools/sort" + tag "samtools/index" + + + // TODO nf-core: Change the test name preferably indicating the test-data and file-format used + test("sarscov2 - bam - single_end") { + + when { + workflow { + """ + // TODO nf-core: define inputs of the workflow here. Example: + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome-ena.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true), + ] + ] + """ + } + } + + then { + assertAll( + { assert workflow.success}, + { assert snapshot(workflow.out).match()} + //TODO nf-core: Add all required assertions to verify the test output. + ) + } + } +} From 24942cd3e9b76ede45c130a30f852423b315207f Mon Sep 17 00:00:00 2001 From: dwells-eit Date: Thu, 22 Jan 2026 09:37:08 +0000 Subject: [PATCH 2/4] Update tests --- .../tests/main.nf.test | 29 +++++---- .../tests/main.nf.test.snap | 59 +++++++++++++++++++ .../tests/nextflow.config | 5 ++ 3 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test.snap create mode 100644 subworkflows/nf-core/fasta_consensus_autocycler/tests/nextflow.config diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test index d5fa27f5667..c79b2e70093 100644 --- a/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test +++ b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test @@ -5,30 +5,34 @@ nextflow_workflow { name "Test Subworkflow FASTA_CONSENSUS_AUTOCYCLER" script "../main.nf" workflow "FASTA_CONSENSUS_AUTOCYCLER" + config "./nextflow.config" tag "subworkflows" tag "subworkflows_nfcore" tag "subworkflows/fasta_consensus_autocycler" - // TODO nf-core: Add tags for all modules used within this subworkflow. Example: - tag "samtools" - tag "samtools/sort" - tag "samtools/index" + tag "autocycler" + tag "autocycler/compress" + tag "autocycler/cluster" + tag "autocycler/trim" + tag "autocycler/resolve" + tag "autocycler/combine" - // TODO nf-core: Change the test name preferably indicating the test-data and file-format used - test("sarscov2 - bam - single_end") { + test("sarscov2 - grouped contigs - fasta") { when { workflow { """ - // TODO nf-core: define inputs of the workflow here. Example: - input[0] = [ - [ id:'test', single_end:false ], // meta map + input[0] = Channel.of( [ - file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome-ena.fasta', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true), + [ id:'test' ], // meta map + [ + // file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome-ena.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true) + ] ] - ] + ) """ } } @@ -37,7 +41,6 @@ nextflow_workflow { assertAll( { assert workflow.success}, { assert snapshot(workflow.out).match()} - //TODO nf-core: Add all required assertions to verify the test output. ) } } diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test.snap b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test.snap new file mode 100644 index 00000000000..c263a4e55d3 --- /dev/null +++ b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test.snap @@ -0,0 +1,59 @@ +{ + "sarscov2 - grouped contigs - fasta": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "consensus_assembly.fasta:md5,7bfb21bf1e4eeb3c5e6ee60c2a803202" + ] + ], + "1": [ + [ + { + "id": "test" + }, + "consensus_assembly.gfa:md5,6812f1bbdbea6722b9726dd9251b080d" + ] + ], + "2": [ + "versions.yml:md5,080d1627ba244eb7685189e9dfe99017", + "versions.yml:md5,3883da014422d8de3303c5472ca2a5e1", + "versions.yml:md5,4dc08195fc243e002c1e48a29ba428fb", + "versions.yml:md5,7af14347c997d5913b790236f3a7e1a2", + "versions.yml:md5,e3c1aed177af57ecbe7581bb3dcf688c" + ], + "consensus_assembly": [ + [ + { + "id": "test" + }, + "consensus_assembly.fasta:md5,7bfb21bf1e4eeb3c5e6ee60c2a803202" + ] + ], + "consensus_assembly_graph": [ + [ + { + "id": "test" + }, + "consensus_assembly.gfa:md5,6812f1bbdbea6722b9726dd9251b080d" + ] + ], + "versions": [ + "versions.yml:md5,080d1627ba244eb7685189e9dfe99017", + "versions.yml:md5,3883da014422d8de3303c5472ca2a5e1", + "versions.yml:md5,4dc08195fc243e002c1e48a29ba428fb", + "versions.yml:md5,7af14347c997d5913b790236f3a7e1a2", + "versions.yml:md5,e3c1aed177af57ecbe7581bb3dcf688c" + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.4" + }, + "timestamp": "2026-01-05T13:26:02.890230918" + } +} \ No newline at end of file diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/tests/nextflow.config b/subworkflows/nf-core/fasta_consensus_autocycler/tests/nextflow.config new file mode 100644 index 00000000000..d3be1be6a9f --- /dev/null +++ b/subworkflows/nf-core/fasta_consensus_autocycler/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: 'AUTOCYCLER_CLUSTER' { + ext.args = "--min_assemblies 1" + } +} From da4313429c86fbb05aaca26e2862e76b8bc33719 Mon Sep 17 00:00:00 2001 From: dwells-eit Date: Mon, 26 Jan 2026 10:56:19 +0000 Subject: [PATCH 3/4] Remove versions channels --- .../nf-core/fasta_consensus_autocycler/main.nf | 9 --------- .../nf-core/fasta_consensus_autocycler/meta.yml | 6 ------ .../tests/main.nf.test | 2 -- .../tests/main.nf.test.snap | 16 +--------------- 4 files changed, 1 insertion(+), 32 deletions(-) diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/main.nf b/subworkflows/nf-core/fasta_consensus_autocycler/main.nf index 0a4bcb5f732..4fa92ea4e75 100644 --- a/subworkflows/nf-core/fasta_consensus_autocycler/main.nf +++ b/subworkflows/nf-core/fasta_consensus_autocycler/main.nf @@ -12,17 +12,13 @@ workflow FASTA_CONSENSUS_AUTOCYCLER { main: - ch_versions = Channel.empty() - AUTOCYCLER_COMPRESS ( ch_grouped_contigs ) - ch_versions = ch_versions.mix(AUTOCYCLER_COMPRESS.out.versions.first()) AUTOCYCLER_CLUSTER ( AUTOCYCLER_COMPRESS.out.gfa ) - ch_versions = ch_versions.mix(AUTOCYCLER_CLUSTER.out.versions.first()) AUTOCYCLER_CLUSTER.out.clusters .flatMap { meta, gfa_list -> @@ -38,12 +34,10 @@ workflow FASTA_CONSENSUS_AUTOCYCLER { AUTOCYCLER_TRIM( ch_clusters ) - ch_versions = ch_versions.mix(AUTOCYCLER_TRIM.out.versions.first()) AUTOCYCLER_RESOLVE( AUTOCYCLER_TRIM.out.gfa ) - ch_versions = ch_versions.mix(AUTOCYCLER_RESOLVE.out.versions.first()) // Rename resolved gfa files to include cluster ID and avoid filename collisions RENAME( @@ -64,7 +58,6 @@ workflow FASTA_CONSENSUS_AUTOCYCLER { AUTOCYCLER_COMBINE( ch_assembly_clusters ) - ch_versions = ch_versions.mix(AUTOCYCLER_COMBINE.out.versions.first()) ch_consensus_assembly = AUTOCYCLER_COMBINE.out.fasta // channel: [ val(meta), fasta ] ch_consensus_assembly_graph = AUTOCYCLER_COMBINE.out.gfa // channel: [ val(meta), gfa ] @@ -73,8 +66,6 @@ workflow FASTA_CONSENSUS_AUTOCYCLER { emit: consensus_assembly = ch_consensus_assembly // channel: [ val(meta), fasta ] consensus_assembly_graph = ch_consensus_assembly_graph // channel: [ val(meta), gfa ] - - versions = ch_versions // channel: [ versions.yml ] } process RENAME { diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/meta.yml b/subworkflows/nf-core/fasta_consensus_autocycler/meta.yml index 2aadbd5f6b2..8ea3eaa62da 100644 --- a/subworkflows/nf-core/fasta_consensus_autocycler/meta.yml +++ b/subworkflows/nf-core/fasta_consensus_autocycler/meta.yml @@ -32,12 +32,6 @@ output: Channel containing consensus assembly graphs Structure: [ val(meta), path(gfa) ] pattern: "*/consensus_assembly.gfa" - - versions: - type: file - description: | - File containing software versions - Structure: [ path(versions.yml) ] - pattern: "versions.yml" authors: - "@dwells-eit" maintainers: diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test index c79b2e70093..e82f9747039 100644 --- a/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test +++ b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test @@ -1,5 +1,3 @@ -// TODO nf-core: Once you have added the required tests, please run the following command to build this file: -// nf-core subworkflows test fasta_consensus_autocycler nextflow_workflow { name "Test Subworkflow FASTA_CONSENSUS_AUTOCYCLER" diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test.snap b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test.snap index c263a4e55d3..ed34df39034 100644 --- a/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test.snap +++ b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test.snap @@ -18,13 +18,6 @@ "consensus_assembly.gfa:md5,6812f1bbdbea6722b9726dd9251b080d" ] ], - "2": [ - "versions.yml:md5,080d1627ba244eb7685189e9dfe99017", - "versions.yml:md5,3883da014422d8de3303c5472ca2a5e1", - "versions.yml:md5,4dc08195fc243e002c1e48a29ba428fb", - "versions.yml:md5,7af14347c997d5913b790236f3a7e1a2", - "versions.yml:md5,e3c1aed177af57ecbe7581bb3dcf688c" - ], "consensus_assembly": [ [ { @@ -40,13 +33,6 @@ }, "consensus_assembly.gfa:md5,6812f1bbdbea6722b9726dd9251b080d" ] - ], - "versions": [ - "versions.yml:md5,080d1627ba244eb7685189e9dfe99017", - "versions.yml:md5,3883da014422d8de3303c5472ca2a5e1", - "versions.yml:md5,4dc08195fc243e002c1e48a29ba428fb", - "versions.yml:md5,7af14347c997d5913b790236f3a7e1a2", - "versions.yml:md5,e3c1aed177af57ecbe7581bb3dcf688c" ] } ], @@ -54,6 +40,6 @@ "nf-test": "0.9.2", "nextflow": "25.04.4" }, - "timestamp": "2026-01-05T13:26:02.890230918" + "timestamp": "2026-01-26T09:07:26.200354507" } } \ No newline at end of file From 69bdc42db22131517724a7eda7bc8e43a3549ab3 Mon Sep 17 00:00:00 2001 From: dwells-eit Date: Wed, 28 Jan 2026 13:47:50 +0000 Subject: [PATCH 4/4] Tidy up scripts delete commented out lines and add indents --- .../fasta_consensus_autocycler/main.nf | 32 +++++++++---------- .../tests/main.nf.test | 1 - 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/main.nf b/subworkflows/nf-core/fasta_consensus_autocycler/main.nf index 4fa92ea4e75..048443fd4c4 100644 --- a/subworkflows/nf-core/fasta_consensus_autocycler/main.nf +++ b/subworkflows/nf-core/fasta_consensus_autocycler/main.nf @@ -21,15 +21,15 @@ workflow FASTA_CONSENSUS_AUTOCYCLER { ) AUTOCYCLER_CLUSTER.out.clusters - .flatMap { meta, gfa_list -> - ( gfa_list instanceof List ? gfa_list: [gfa_list] ) - .collect { gfa -> [meta, gfa] } // Separate gfas, each with a meta - } - .map { meta, file -> - def cluster_id = (file.parent.name) // Add cluster id to meta - tuple( meta + [cluster: cluster_id], file ) - } - .set{ ch_clusters } // channel: [ val(meta), gfa] + .flatMap { meta, gfa_list -> + ( gfa_list instanceof List ? gfa_list: [gfa_list] ) + .collect { gfa -> [meta, gfa] } // Separate gfas, each with a meta + } + .map { meta, file -> + def cluster_id = (file.parent.name) // Add cluster id to meta + [ meta + [cluster: cluster_id], file ] + } + .set{ ch_clusters } // channel: [ val(meta), gfa] AUTOCYCLER_TRIM( ch_clusters @@ -47,13 +47,13 @@ workflow FASTA_CONSENSUS_AUTOCYCLER { // Group clusters based on meta, ignoring cluster id RENAME.out.renamed - .map{ meta, file -> - def new_meta = meta.clone() - new_meta.remove("cluster") - tuple( new_meta, file) - } - .groupTuple() - .set{ ch_assembly_clusters } // channel: [ meta, [ cluster1, cluster2, ... ] ] + .map{ meta, file -> + def new_meta = meta.clone() + new_meta.remove("cluster") + tuple( new_meta, file) + } + .groupTuple() + .set{ ch_assembly_clusters } // channel: [ meta, [ cluster1, cluster2, ... ] ] AUTOCYCLER_COMBINE( ch_assembly_clusters diff --git a/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test index e82f9747039..824568fb968 100644 --- a/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test +++ b/subworkflows/nf-core/fasta_consensus_autocycler/tests/main.nf.test @@ -25,7 +25,6 @@ nextflow_workflow { [ [ id:'test' ], // meta map [ - // file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome-ena.fasta', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true) ]