diff --git a/modules/nf-core/homer/annotatepeaks/environment.yml b/modules/nf-core/homer/annotatepeaks/environment.yml index 3a556e4c9f96..52d159af06fa 100644 --- a/modules/nf-core/homer/annotatepeaks/environment.yml +++ b/modules/nf-core/homer/annotatepeaks/environment.yml @@ -4,9 +4,9 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::bioconductor-deseq2=1.42.0 - - bioconda::bioconductor-edger=4.0.16 - - bioconda::homer=4.11 - - bioconda::samtools=1.21 - - conda-forge::r-essentials=4.3 + - bioconda::bioconductor-deseq2=1.46.0 + - bioconda::bioconductor-edger=4.4.0 + - bioconda::homer=5.1 + - bioconda::samtools=1.22.1 + - conda-forge::r-essentials=4.4 - conda-forge::wget=1.21.4 diff --git a/modules/nf-core/homer/annotatepeaks/main.nf b/modules/nf-core/homer/annotatepeaks/main.nf index 053d09d67ad3..2d8d41116dc0 100644 --- a/modules/nf-core/homer/annotatepeaks/main.nf +++ b/modules/nf-core/homer/annotatepeaks/main.nf @@ -1,10 +1,13 @@ process HOMER_ANNOTATEPEAKS { tag "${meta.id}" label 'process_medium' + conda "${moduleDir}/environment.yml" + // singularity build url: https://wave.seqera.io/view/builds/bd-9c603739ae7d4fd3_1 + // docker build url: https://wave.seqera.io/view/builds/bd-08c7bb832e96c6bd_1 container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/0f/0fe4a3875b78dce3c66b43fb96489769cc32e55e329e2525d2af09096af2252a/data' - : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:a8f4c58755bb281b'}" + ? 'oras://community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:9c603739ae7d4fd3' + : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:08c7bb832e96c6bd'}" input: tuple val(meta), path(peak) @@ -22,7 +25,7 @@ process HOMER_ANNOTATEPEAKS { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def VERSION = '4.11' + def VERSION = '5.1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ annotatePeaks.pl \\ @@ -41,7 +44,7 @@ process HOMER_ANNOTATEPEAKS { stub: def prefix = task.ext.prefix ?: "${meta.id}" - def VERSION = '4.11' + def VERSION = '5.1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ touch ${prefix}.annotatePeaks.txt diff --git a/modules/nf-core/homer/findpeaks/environment.yml b/modules/nf-core/homer/findpeaks/environment.yml index 3a556e4c9f96..52d159af06fa 100644 --- a/modules/nf-core/homer/findpeaks/environment.yml +++ b/modules/nf-core/homer/findpeaks/environment.yml @@ -4,9 +4,9 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::bioconductor-deseq2=1.42.0 - - bioconda::bioconductor-edger=4.0.16 - - bioconda::homer=4.11 - - bioconda::samtools=1.21 - - conda-forge::r-essentials=4.3 + - bioconda::bioconductor-deseq2=1.46.0 + - bioconda::bioconductor-edger=4.4.0 + - bioconda::homer=5.1 + - bioconda::samtools=1.22.1 + - conda-forge::r-essentials=4.4 - conda-forge::wget=1.21.4 diff --git a/modules/nf-core/homer/findpeaks/main.nf b/modules/nf-core/homer/findpeaks/main.nf index f9a5c78b7429..7bd0927d0491 100644 --- a/modules/nf-core/homer/findpeaks/main.nf +++ b/modules/nf-core/homer/findpeaks/main.nf @@ -1,17 +1,23 @@ process HOMER_FINDPEAKS { tag "${meta.id}" label 'process_medium' + conda "${moduleDir}/environment.yml" + // singularity build url: https://wave.seqera.io/view/builds/bd-9c603739ae7d4fd3_1 + // docker build url: https://wave.seqera.io/view/builds/bd-08c7bb832e96c6bd_1 container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/0f/0fe4a3875b78dce3c66b43fb96489769cc32e55e329e2525d2af09096af2252a/data' - : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:a8f4c58755bb281b'}" + ? 'oras://community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:9c603739ae7d4fd3' + : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:08c7bb832e96c6bd'}" input: + val(style) tuple val(meta), path(tagDir) + tuple val(meta2), path(controlTagDir) path uniqmap output: - tuple val(meta), path("*.peaks.txt"), emit: txt + tuple val(meta), path("*.txt"), emit: txt + tuple val(meta), path("*.gtf"), optional: true, emit: gtf path "versions.yml", emit: versions when: @@ -19,16 +25,41 @@ process HOMER_FINDPEAKS { script: def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: uniqmap ? "${meta.id}-${uniqmap.baseName}" : "${meta.id}" + def prefix = task.ext.prefix ?: "${meta.id}" def uniqmap_flag = uniqmap ? "-uniqmap ${uniqmap}" : "" - def VERSION = '4.11' - // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. - """ + def control_flag = controlTagDir ? "-i ${controlTagDir}" : "" + def control_suffix = controlTagDir ? "_vs_${meta2.id}" : "" + def VERSION = '5.1' + + // Validate style + def valid_styles = ['factor', 'histone', 'groseq', 'tss', 'dnase', 'super', 'mC'] + if (!valid_styles.contains(style)) { + error "style must be one of: ${valid_styles.join(', ')}" + } + // Determine output suffix based on style + def output_suffix_map = [ + 'factor': 'peaks.txt', + 'histone': 'regions.txt', + 'groseq': 'transcripts.txt', + 'tss': 'tss.txt', + 'dnase': 'peaks.txt', + 'super': 'superEnhancers.txt', + 'mC': 'regions.txt' + ] + def output_suffix = output_suffix_map[style] + def output_filename = "${prefix}${control_suffix}_${output_suffix}" + + def groseq_gtf_arg = style == "groseq" ? "-gtf ${prefix}${control_suffix}_transcripts.gtf" : "" + + """ findPeaks \\ ${tagDir} \\ + -style ${style} \\ + ${control_flag} \\ ${args} \\ - -o ${prefix}.peaks.txt \\ + ${groseq_gtf_arg} \\ + -o ${output_filename} \\ ${uniqmap_flag} cat <<-END_VERSIONS > versions.yml @@ -39,11 +70,25 @@ process HOMER_FINDPEAKS { stub: def prefix = task.ext.prefix ?: "${meta.id}" - def VERSION = '4.11' - // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + def control_suffix = controlTagDir ? "_vs_${meta2.id}" : "" + def VERSION = '5.1' + + def output_suffix_map = [ + 'factor': 'peaks.txt', + 'histone': 'regions.txt', + 'groseq': 'transcripts.txt', + 'tss': 'tss.txt', + 'dnase': 'peaks.txt', + 'super': 'superEnhancers.txt', + 'mC': 'regions.txt' + ] + def output_suffix = output_suffix_map[style] + def output_filename = "${prefix}${control_suffix}_${output_suffix}" + def gtf_filename = "${prefix}${control_suffix}_transcripts.gtf" """ - touch ${prefix}.peaks.txt + touch ${output_filename} + ${style == 'groseq' ? "touch ${gtf_filename}" : ''} cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/homer/findpeaks/meta.yml b/modules/nf-core/homer/findpeaks/meta.yml index 9241c014cf27..7e2c9a98c55d 100644 --- a/modules/nf-core/homer/findpeaks/meta.yml +++ b/modules/nf-core/homer/findpeaks/meta.yml @@ -15,6 +15,14 @@ tools: licence: ["GPL-3.0-or-later"] identifier: biotools:homer input: + - style: + type: string + description: | + One of factor, histone, groseq, tss, dnase, super or mC. See the homer + findPeak documentation for more information. The choice of style does + affect which parameters must be passed in through `ext.args`, and affects + the suffix of the output file (e.g. if style is factor, then the file output + to the txt channel will be *_peaks.txt. See output for more information.) - - meta: type: map description: | @@ -24,10 +32,19 @@ input: type: directory description: "The 'Tag Directory'" pattern: "tagDir" + - - meta2: + type: map + description: | + Groovy map containing sample information for the control sample + e.g. [ id: "control", single_end: false ] + - controlTagDir: + type: directory + description: "The 'Tag Directory' for the control sample" + pattern: "controlTagDir" - uniqmap: type: directory description: "(directory of binary files specifying uniquely mappable locations) - Download from http://biowhat.ucsd.edu/homer/groseq/" + Download from http://biowha t.ucsd.edu/homer/groseq/" pattern: "uniqmap/" output: txt: @@ -36,7 +53,21 @@ output: description: | Groovy Map containing sample information e.g. [ id:'test', single_end:false ] - - "*.peaks.txt": + - "*.txt": + type: file + description: | + One of *_peaks.txt, *_regions, *_transcripts.txt, + *_tss.txt, *_superEnhancer.txt. Which depends on the `style`, e.g. for + style factor, the output txt file would be *_peaks.txt + pattern: "*.txt" + ontologies: [] + gtf: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.gtf": type: file description: "Peaks in txt file" pattern: "*.peaks.txt" @@ -52,3 +83,4 @@ authors: - "@edmundmiller" maintainers: - "@edmundmiller" + - "@cmatkhan" diff --git a/modules/nf-core/homer/findpeaks/tests/main.nf.test b/modules/nf-core/homer/findpeaks/tests/main.nf.test index a72a0fa561a7..238eaccaed52 100644 --- a/modules/nf-core/homer/findpeaks/tests/main.nf.test +++ b/modules/nf-core/homer/findpeaks/tests/main.nf.test @@ -49,8 +49,10 @@ nextflow_process { when { process { """ - input[0] = HOMER_MAKETAGDIRECTORY.out.tagdir - input[1] = [] + input[0] = "factor" + input[1] = HOMER_MAKETAGDIRECTORY.out.tagdir + input[2] = [[:], []] + input[3] = [] """ } } @@ -71,8 +73,10 @@ nextflow_process { when { process { """ - input[0] = HOMER_MAKETAGDIRECTORY.out.tagdir - input[1] = [] + input[0] = "factor" + input[1] = HOMER_MAKETAGDIRECTORY.out.tagdir + input[2] = [[:], []] + input[3] = [] """ } } @@ -92,8 +96,10 @@ nextflow_process { when { process { """ - input[0] = HOMER_MAKETAGDIRECTORY.out.tagdir - input[1] = UNZIP.out.unzipped_archive.map { it[1] } + input[0] = "factor" + input[1] = HOMER_MAKETAGDIRECTORY.out.tagdir + input[2] = [[:], []] + input[3] = UNZIP.out.unzipped_archive.map { it[1] } """ } } @@ -111,4 +117,4 @@ nextflow_process { ) } } -} \ No newline at end of file +} diff --git a/modules/nf-core/homer/findpeaks/tests/main.nf.test.snap b/modules/nf-core/homer/findpeaks/tests/main.nf.test.snap index c658f18a18c4..80e307329ae9 100644 --- a/modules/nf-core/homer/findpeaks/tests/main.nf.test.snap +++ b/modules/nf-core/homer/findpeaks/tests/main.nf.test.snap @@ -7,18 +7,24 @@ { "id": "test" }, - "test.peaks.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + "test_peaks.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "1": [ + + ], + "2": [ "versions.yml:md5,12c3e88a3eeb96208a1d352504ebebfa" + ], + "gtf": [ + ], "txt": [ [ { "id": "test" }, - "test.peaks.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + "test_peaks.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "versions": [ @@ -28,9 +34,9 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.1" + "nextflow": "25.04.7" }, - "timestamp": "2024-11-23T14:32:17.860543" + "timestamp": "2025-10-06T09:30:40.82970252" }, "tagdir": { "content": [ @@ -40,18 +46,24 @@ { "id": "test" }, - "test.peaks.txt:md5,86e15beaa4b439585786478e58418c0c" + "test_peaks.txt:md5,3830a3d6c88718aac8794867ece68999" ] ], "1": [ + + ], + "2": [ "versions.yml:md5,12c3e88a3eeb96208a1d352504ebebfa" + ], + "gtf": [ + ], "txt": [ [ { "id": "test" }, - "test.peaks.txt:md5,86e15beaa4b439585786478e58418c0c" + "test_peaks.txt:md5,3830a3d6c88718aac8794867ece68999" ] ], "versions": [ @@ -60,10 +72,10 @@ } ], "meta": { - "nf-test": "0.8.4", - "nextflow": "24.03.0" + "nf-test": "0.9.2", + "nextflow": "25.04.7" }, - "timestamp": "2024-05-17T13:56:22.119853182" + "timestamp": "2025-10-06T09:37:11.880037812" }, "sarscov2 - tagdir - uniqmap": { "content": [ @@ -73,18 +85,24 @@ { "id": "test" }, - "test-uniqmap.GRCh38_chr21.peaks.txt:md5,d96e7bba4f4fe827a18acae200b422a4" + "test_peaks.txt:md5,49bc9b650b2acd03adb0f201493a6863" ] ], "1": [ + + ], + "2": [ "versions.yml:md5,12c3e88a3eeb96208a1d352504ebebfa" + ], + "gtf": [ + ], "txt": [ [ { "id": "test" }, - "test-uniqmap.GRCh38_chr21.peaks.txt:md5,d96e7bba4f4fe827a18acae200b422a4" + "test_peaks.txt:md5,49bc9b650b2acd03adb0f201493a6863" ] ], "versions": [ @@ -92,12 +110,12 @@ ] }, "# uniqMapDirectory = uniqmap.GRCh38_chr21.50nt", - "# cmd = findPeaks test_tagdir -style factor -o test-uniqmap.GRCh38_chr21.peaks.txt -uniqmap uniqmap.GRCh38_chr21.50nt" + "# cmd = findPeaks test_tagdir -style factor -style factor -o test_peaks.txt -uniqmap uniqmap.GRCh38_chr21.50nt" ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.2" + "nextflow": "25.04.7" }, - "timestamp": "2024-12-07T18:32:39.16634" + "timestamp": "2025-10-06T09:37:21.668112406" } } \ No newline at end of file diff --git a/modules/nf-core/homer/maketagdirectory/environment.yml b/modules/nf-core/homer/maketagdirectory/environment.yml index 3a556e4c9f96..52d159af06fa 100644 --- a/modules/nf-core/homer/maketagdirectory/environment.yml +++ b/modules/nf-core/homer/maketagdirectory/environment.yml @@ -4,9 +4,9 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::bioconductor-deseq2=1.42.0 - - bioconda::bioconductor-edger=4.0.16 - - bioconda::homer=4.11 - - bioconda::samtools=1.21 - - conda-forge::r-essentials=4.3 + - bioconda::bioconductor-deseq2=1.46.0 + - bioconda::bioconductor-edger=4.4.0 + - bioconda::homer=5.1 + - bioconda::samtools=1.22.1 + - conda-forge::r-essentials=4.4 - conda-forge::wget=1.21.4 diff --git a/modules/nf-core/homer/maketagdirectory/main.nf b/modules/nf-core/homer/maketagdirectory/main.nf index 8d662a6845d7..d0af45274571 100644 --- a/modules/nf-core/homer/maketagdirectory/main.nf +++ b/modules/nf-core/homer/maketagdirectory/main.nf @@ -1,10 +1,13 @@ process HOMER_MAKETAGDIRECTORY { tag "${meta.id}" label 'process_medium' + conda "${moduleDir}/environment.yml" + // singularity build url: https://wave.seqera.io/view/builds/bd-9c603739ae7d4fd3_1 + // docker build url: https://wave.seqera.io/view/builds/bd-08c7bb832e96c6bd_1 container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/0f/0fe4a3875b78dce3c66b43fb96489769cc32e55e329e2525d2af09096af2252a/data' - : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:a8f4c58755bb281b'}" + ? 'oras://community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:9c603739ae7d4fd3' + : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:08c7bb832e96c6bd'}" input: tuple val(meta), path(bam) @@ -21,7 +24,7 @@ process HOMER_MAKETAGDIRECTORY { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def VERSION = '4.11' + def VERSION = '5.1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ makeTagDirectory \\ @@ -39,7 +42,7 @@ process HOMER_MAKETAGDIRECTORY { stub: def prefix = task.ext.prefix ?: "${meta.id}" - def VERSION = '4.11' + def VERSION = '5.1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ diff --git a/modules/nf-core/homer/makeucscfile/environment.yml b/modules/nf-core/homer/makeucscfile/environment.yml index 3a556e4c9f96..52d159af06fa 100644 --- a/modules/nf-core/homer/makeucscfile/environment.yml +++ b/modules/nf-core/homer/makeucscfile/environment.yml @@ -4,9 +4,9 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::bioconductor-deseq2=1.42.0 - - bioconda::bioconductor-edger=4.0.16 - - bioconda::homer=4.11 - - bioconda::samtools=1.21 - - conda-forge::r-essentials=4.3 + - bioconda::bioconductor-deseq2=1.46.0 + - bioconda::bioconductor-edger=4.4.0 + - bioconda::homer=5.1 + - bioconda::samtools=1.22.1 + - conda-forge::r-essentials=4.4 - conda-forge::wget=1.21.4 diff --git a/modules/nf-core/homer/makeucscfile/main.nf b/modules/nf-core/homer/makeucscfile/main.nf index b1f193346e05..47871ebbdfc1 100644 --- a/modules/nf-core/homer/makeucscfile/main.nf +++ b/modules/nf-core/homer/makeucscfile/main.nf @@ -1,10 +1,13 @@ process HOMER_MAKEUCSCFILE { tag "${meta.id}" label 'process_medium' + conda "${moduleDir}/environment.yml" + // singularity build url: https://wave.seqera.io/view/builds/bd-9c603739ae7d4fd3_1 + // docker build url: https://wave.seqera.io/view/builds/bd-08c7bb832e96c6bd_1 container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/0f/0fe4a3875b78dce3c66b43fb96489769cc32e55e329e2525d2af09096af2252a/data' - : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:a8f4c58755bb281b'}" + ? 'oras://community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:9c603739ae7d4fd3' + : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:08c7bb832e96c6bd'}" input: tuple val(meta), path(tagDir) @@ -19,7 +22,7 @@ process HOMER_MAKEUCSCFILE { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def VERSION = '4.11' + def VERSION = '5.1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ makeUCSCfile \\ diff --git a/modules/nf-core/homer/mergepeaks/environment.yml b/modules/nf-core/homer/mergepeaks/environment.yml new file mode 100644 index 000000000000..52d159af06fa --- /dev/null +++ b/modules/nf-core/homer/mergepeaks/environment.yml @@ -0,0 +1,12 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::bioconductor-deseq2=1.46.0 + - bioconda::bioconductor-edger=4.4.0 + - bioconda::homer=5.1 + - bioconda::samtools=1.22.1 + - conda-forge::r-essentials=4.4 + - conda-forge::wget=1.21.4 diff --git a/modules/nf-core/homer/mergepeaks/main.nf b/modules/nf-core/homer/mergepeaks/main.nf new file mode 100644 index 000000000000..1b041e99024d --- /dev/null +++ b/modules/nf-core/homer/mergepeaks/main.nf @@ -0,0 +1,52 @@ +process HOMER_MERGEPEAKS { + tag "$meta.id" + label 'process_single' + + conda "${moduleDir}/environment.yml" + // singularity build url: https://wave.seqera.io/view/builds/bd-9c603739ae7d4fd3_1 + // docker build url: https://wave.seqera.io/view/builds/bd-08c7bb832e96c6bd_1 + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'oras://community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:9c603739ae7d4fd3' + : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:08c7bb832e96c6bd'}" + + input: + tuple val(meta), path(peaks) // peaks can be a list of peak files + + output: + tuple val(meta), path("*.txt"), emit: 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}" + "_merged_peaks" + def peak_files = peaks instanceof List ? peaks.join(' ') : peaks + def VERSION = '5.1' + + """ + mergePeaks \\ + $args \\ + -prefix ${prefix} \\ + $peak_files \\ + > ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + homer: ${VERSION} + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}_merged_peaks" + def VERSION = '5.1' + """ + touch ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + homer: ${VERSION} + END_VERSIONS + """ +} diff --git a/modules/nf-core/homer/mergepeaks/meta.yml b/modules/nf-core/homer/mergepeaks/meta.yml new file mode 100644 index 000000000000..3328ebafb36a --- /dev/null +++ b/modules/nf-core/homer/mergepeaks/meta.yml @@ -0,0 +1,55 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "homer_mergepeaks" +description: Merge peak files from multiple experiments or replicates into a unified peak set +keywords: + - peaks + - merge + - chipseq + - chipexo + - consensus +tools: + - homer: + description: | + HOMER (Hypergeometric Optimization of Motif EnRichment) is a suite of tools for Motif Discovery and next-gen sequencing analysis. + homepage: "http://homer.ucsd.edu/homer/index.html" + documentation: "http://homer.ucsd.edu/homer/" + tool_dev_url: "http://homer.ucsd.edu/homer/ngs/peaks.html" + doi: 10.1016/j.molcel.2010.05.004. + licence: ["GPL-3.0-or-later"] + identifier: biotools:homer +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'merged_peaks' ] + - peaks: + type: file + description: Peak files from HOMER findPeaks in HOMER peak format (*.txt). Can be a single file or list of files. + pattern: "*.txt" + +output: + txt: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'merged_peaks' ] + - "*.txt": + type: file + description: Merged peak file in HOMER peak format + pattern: "*.txt" + ontologies: + - edam: https://bioportal.bioontology.org/ontologies/EDAM?p=classes&conceptid=format_3475 # tsv + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML + +authors: + - "@cmatKhan" +maintainers: + - "@cmatKhan" diff --git a/modules/nf-core/homer/mergepeaks/tests/main.nf.test b/modules/nf-core/homer/mergepeaks/tests/main.nf.test new file mode 100644 index 000000000000..809cb9ebd856 --- /dev/null +++ b/modules/nf-core/homer/mergepeaks/tests/main.nf.test @@ -0,0 +1,124 @@ +nextflow_process { + + name "Test Process HOMER_MERGEPEAKS" + script "../main.nf" + process "HOMER_MERGEPEAKS" + config "./nextflow.config" + + tag "modules" + tag "modules_nfcore" + tag "homer" + tag "homer/mergepeaks" + tag "homer/findpeaks" + tag "homer/maketagdirectory" + + setup { + run("HOMER_MAKETAGDIRECTORY", alias: "MAKETAGDIR_SAMPLE1") { + script "../../maketagdirectory/main.nf" + process { + """ + input[0] = [ + [ id:'sample1' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/bed/test.bed', checkIfExists: true) + ] + input[1] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + """ + } + } + + run("HOMER_MAKETAGDIRECTORY", alias: "MAKETAGDIR_SAMPLE2") { + script "../../maketagdirectory/main.nf" + process { + """ + input[0] = [ + [ id:'sample2' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/bed/test2.bed', checkIfExists: true) + ] + input[1] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + """ + } + } + + run("HOMER_FINDPEAKS", alias: "FINDPEAKS_SAMPLE1") { + script "../../findpeaks/main.nf" + process { + """ + input[0] = "factor" + input[1] = MAKETAGDIR_SAMPLE1.out.tagdir + input[2] = [[:], []] + input[3] = [] + """ + } + } + + run("HOMER_FINDPEAKS", alias: "FINDPEAKS_SAMPLE2") { + script "../../findpeaks/main.nf" + process { + """ + input[0] = "factor" + input[1] = MAKETAGDIR_SAMPLE2.out.tagdir + input[2] = [[:], []] + input[3] = [] + """ + } + } + } + + test("sarscov2 - bed - merge two peak files") { + + when { + process { + """ + peaks = Channel.empty() + .mix( + FINDPEAKS_SAMPLE1.out.txt.map { it[1] }, + FINDPEAKS_SAMPLE2.out.txt.map { it[1] } + ) + .collect() + .map { [ [id:'merged'], it ] } + + input[0] = peaks + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + file(process.out.txt[0][1]).name, + process.out.versions + ).match() + } + ) + } + } + + test("sarscov2 - bed - merge two peak files - stub") { + + options "-stub" + + when { + process { + """ + peaks = Channel.empty() + .mix( + FINDPEAKS_SAMPLE1.out.txt.map { it[1] }, + FINDPEAKS_SAMPLE2.out.txt.map { it[1] } + ) + .collect() + .map { [ [id:'merged'], it ] } + + input[0] = peaks + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match("stub") } + ) + } + } +} diff --git a/modules/nf-core/homer/mergepeaks/tests/main.nf.test.snap b/modules/nf-core/homer/mergepeaks/tests/main.nf.test.snap new file mode 100644 index 000000000000..3f7b48c76c8d --- /dev/null +++ b/modules/nf-core/homer/mergepeaks/tests/main.nf.test.snap @@ -0,0 +1,48 @@ +{ + "sarscov2 - bed - merge two peak files": { + "content": [ + "merged_peaks.txt", + [ + "versions.yml:md5,a383523aae5048d4b28718f7ba1d8526" + ] + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.7" + }, + "timestamp": "2025-10-05T13:14:52.683370026" + }, + "stub": { + "content": [ + { + "0": [ + [ + { + "id": "merged" + }, + "merged_peaks.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,5985f7630d53ae0605c2f459e43439c2" + ], + "txt": [ + [ + { + "id": "merged" + }, + "merged_peaks.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,5985f7630d53ae0605c2f459e43439c2" + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.7" + }, + "timestamp": "2025-10-05T13:14:58.514229717" + } +} \ No newline at end of file diff --git a/modules/nf-core/homer/mergepeaks/tests/nextflow.config b/modules/nf-core/homer/mergepeaks/tests/nextflow.config new file mode 100644 index 000000000000..fc073f24d28e --- /dev/null +++ b/modules/nf-core/homer/mergepeaks/tests/nextflow.config @@ -0,0 +1,17 @@ +process { + withName: 'MAKETAGDIR_SAMPLE1' { + ext.args = '-format bed' + } + withName: 'MAKETAGDIR_SAMPLE2' { + ext.args = '-format bed' + } + withName: 'FINDPEAKS_SAMPLE1' { + ext.args = '-style factor' + } + withName: 'FINDPEAKS_SAMPLE2' { + ext.args = '-style factor' + } + withName: 'HOMER_MERGEPEAKS' { + ext.prefix = 'merged_peaks' + } +} diff --git a/modules/nf-core/homer/pos2bed/environment.yml b/modules/nf-core/homer/pos2bed/environment.yml index 3a556e4c9f96..52d159af06fa 100644 --- a/modules/nf-core/homer/pos2bed/environment.yml +++ b/modules/nf-core/homer/pos2bed/environment.yml @@ -4,9 +4,9 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::bioconductor-deseq2=1.42.0 - - bioconda::bioconductor-edger=4.0.16 - - bioconda::homer=4.11 - - bioconda::samtools=1.21 - - conda-forge::r-essentials=4.3 + - bioconda::bioconductor-deseq2=1.46.0 + - bioconda::bioconductor-edger=4.4.0 + - bioconda::homer=5.1 + - bioconda::samtools=1.22.1 + - conda-forge::r-essentials=4.4 - conda-forge::wget=1.21.4 diff --git a/modules/nf-core/homer/pos2bed/main.nf b/modules/nf-core/homer/pos2bed/main.nf index 84d482433ca3..9507dc45a4e6 100644 --- a/modules/nf-core/homer/pos2bed/main.nf +++ b/modules/nf-core/homer/pos2bed/main.nf @@ -1,10 +1,13 @@ process HOMER_POS2BED { tag "${meta.id}" label 'process_medium' + conda "${moduleDir}/environment.yml" + // singularity build url: https://wave.seqera.io/view/builds/bd-9c603739ae7d4fd3_1 + // docker build url: https://wave.seqera.io/view/builds/bd-08c7bb832e96c6bd_1 container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/0f/0fe4a3875b78dce3c66b43fb96489769cc32e55e329e2525d2af09096af2252a/data' - : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:a8f4c58755bb281b'}" + ? 'oras://community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:9c603739ae7d4fd3' + : 'community.wave.seqera.io/library/bioconductor-deseq2_bioconductor-edger_homer_samtools_pruned:08c7bb832e96c6bd'}" input: tuple val(meta), path(peaks) @@ -19,7 +22,7 @@ process HOMER_POS2BED { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def VERSION = '4.11' + def VERSION = '5.1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ pos2bed.pl ${peaks} > ${prefix}.bed @@ -32,7 +35,7 @@ process HOMER_POS2BED { stub: def prefix = task.ext.prefix ?: "${meta.id}" - def VERSION = '4.11' + def VERSION = '5.1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ diff --git a/modules/nf-core/homer/pos2bed/tests/main.nf.test b/modules/nf-core/homer/pos2bed/tests/main.nf.test index aac8138c9ed0..f845389e862d 100644 --- a/modules/nf-core/homer/pos2bed/tests/main.nf.test +++ b/modules/nf-core/homer/pos2bed/tests/main.nf.test @@ -33,8 +33,10 @@ nextflow_process { script "../../findpeaks/main.nf" process { """ - input[0] = HOMER_MAKETAGDIRECTORY.out.tagdir - input[1] = [] + input[0] = "factor" + input[1] = HOMER_MAKETAGDIRECTORY.out.tagdir + input[2] = [[:], []] + input[3] = [] """ } } @@ -80,4 +82,4 @@ nextflow_process { } -} \ No newline at end of file +} diff --git a/modules/nf-core/homer/pos2bed/tests/main.nf.test.snap b/modules/nf-core/homer/pos2bed/tests/main.nf.test.snap index 6cd500510c24..0c1203de2db9 100644 --- a/modules/nf-core/homer/pos2bed/tests/main.nf.test.snap +++ b/modules/nf-core/homer/pos2bed/tests/main.nf.test.snap @@ -40,7 +40,7 @@ { "id": "test" }, - "test.bed:md5,5d6ddd9c7e621a66f6f045b9b5abecb4" + "test.bed:md5,78a99fcbdb73d7e932c8127e48772851" ] ], "1": [ @@ -51,7 +51,7 @@ { "id": "test" }, - "test.bed:md5,5d6ddd9c7e621a66f6f045b9b5abecb4" + "test.bed:md5,78a99fcbdb73d7e932c8127e48772851" ] ], "versions": [ @@ -60,9 +60,9 @@ } ], "meta": { - "nf-test": "0.8.4", - "nextflow": "24.03.0" + "nf-test": "0.9.2", + "nextflow": "25.04.7" }, - "timestamp": "2024-05-17T14:35:30.500600143" + "timestamp": "2025-10-06T13:59:12.002000386" } } \ No newline at end of file diff --git a/subworkflows/nf-core/homer_groseq/main.nf b/subworkflows/nf-core/homer_groseq/main.nf index cd30b98cc207..c714cd304f9b 100644 --- a/subworkflows/nf-core/homer_groseq/main.nf +++ b/subworkflows/nf-core/homer_groseq/main.nf @@ -47,7 +47,11 @@ workflow HOMER_GROSEQ { /* * Find transcripts directly from GRO-Seq */ - HOMER_FINDPEAKS(HOMER_MAKETAGDIRECTORY.out.tagdir, ch_uniqmap) + HOMER_FINDPEAKS( + "groseq", + HOMER_MAKETAGDIRECTORY.out.tagdir, + [[:], []], + ch_uniqmap) ch_versions = ch_versions.mix(HOMER_FINDPEAKS.out.versions) /* diff --git a/subworkflows/nf-core/homer_groseq/tests/main.nf.test.snap b/subworkflows/nf-core/homer_groseq/tests/main.nf.test.snap index 61e8eb64289c..0a187cbd672b 100644 --- a/subworkflows/nf-core/homer_groseq/tests/main.nf.test.snap +++ b/subworkflows/nf-core/homer_groseq/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test" }, - "test.peaks.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + "test_transcripts.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], [ @@ -26,9 +26,9 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.1" + "nextflow": "25.04.7" }, - "timestamp": "2024-11-23T20:49:13.598633" + "timestamp": "2025-10-06T14:02:12.275198449" }, "versions": { "content": [ @@ -52,7 +52,7 @@ { "id": "test" }, - "test.peaks.txt:md5,470ad70471ef668cab50d9c41e5b124c" + "test_transcripts.txt:md5,40c6260ed6448afde7f03b94c5481f62" ] ], [ @@ -60,7 +60,7 @@ { "id": "test" }, - "test.bed:md5,470ad70471ef668cab50d9c41e5b124c" + "test.bed:md5,40c6260ed6448afde7f03b94c5481f62" ] ], { @@ -71,9 +71,9 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.1" + "nextflow": "25.04.7" }, - "timestamp": "2024-11-23T20:47:40.376043" + "timestamp": "2025-10-06T13:59:23.186180977" }, "Should run HOMER_GROSEQ with BED input": { "content": [ @@ -83,7 +83,7 @@ { "id": "test" }, - "test.peaks.txt:md5,0b0b174b135fd5404a9b462e27ab4ce1" + "test_transcripts.txt:md5,560d3b591f1f5b0ab0a1f8a71668a84f" ] ], [ @@ -91,7 +91,7 @@ { "id": "test" }, - "test.bed:md5,0b0b174b135fd5404a9b462e27ab4ce1" + "test.bed:md5,560d3b591f1f5b0ab0a1f8a71668a84f" ] ], { @@ -102,19 +102,19 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.1" + "nextflow": "25.04.7" }, - "timestamp": "2024-11-23T20:47:47.733612" + "timestamp": "2025-10-06T13:59:28.660340994" }, "Test files from GROseq tutorial with uniqmap": { "content": [ - 15368354, + 15368355, [ [ { "id": "test" }, - "test-uniqmap.GRCh38_chr21.50nt.peaks.txt:md5,3220d07ce56785d77045282345ddf1cd" + "test_transcripts.txt:md5,e15075d53b1e080fd73cf7f3c46cc8c6" ] ], [ @@ -122,11 +122,11 @@ { "id": "test" }, - "test.bed:md5,49433f826697cd237dfdb740a0cb2c54" + "test.bed:md5,72d4827191c3295f737277798459c1f3" ] ], - "# uniqMapDirectory = uniqmap.GRCh38_chr21.50nt.zip", - "# cmd = findPeaks test_tagdir -o test-uniqmap.GRCh38_chr21.50nt.peaks.txt -uniqmap uniqmap.GRCh38_chr21.50nt.zip", + "chr2\t254807\t44846678\tchr2-1-0\t0\t+", + "chr5\t66289264\t180620735\tchr5-1-1\t0\t-", { "HOMER_GROSEQ:HOMER_POS2BED": { "homer": 4.11 @@ -135,8 +135,8 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.2" + "nextflow": "25.04.7" }, - "timestamp": "2024-12-07T17:59:14.024175" + "timestamp": "2025-10-06T14:02:06.815694413" } } \ No newline at end of file diff --git a/subworkflows/nf-core/homer_peakcalling/main.nf b/subworkflows/nf-core/homer_peakcalling/main.nf new file mode 100644 index 000000000000..0cc6f8e6312b --- /dev/null +++ b/subworkflows/nf-core/homer_peakcalling/main.nf @@ -0,0 +1,179 @@ +/* + * Peak calling workflow with HOMER + */ +include { HOMER_MAKETAGDIRECTORY as HOMER_MAKETAGDIRECTORY_EXP } from '../../../modules/nf-core/homer/maketagdirectory/main' +include { HOMER_MAKETAGDIRECTORY as HOMER_MAKETAGDIRECTORY_CNTRL } from'../../../modules/nf-core/homer/maketagdirectory/main' +include { HOMER_MAKEUCSCFILE } from '../../../modules/nf-core/homer/makeucscfile/main' +include { HOMER_FINDPEAKS } from '../../../modules/nf-core/homer/findpeaks/main' +include { HOMER_MERGEPEAKS } from '../../../modules/nf-core/homer/mergepeaks/main' +include { HOMER_ANNOTATEPEAKS as HOMER_ANNOTATEPEAKS_INDIVIDUAL } from '../../../modules/nf-core/homer/annotatepeaks/main' +include { HOMER_ANNOTATEPEAKS as HOMER_ANNOTATEPEAKS_MERGED } from '../../../modules/nf-core/homer/annotatepeaks/main' +include { HOMER_ANNOTATEPEAKS as HOMER_QUANTIFYPEAKS } from '../../../modules/nf-core/homer/annotatepeaks/main' +include { HOMER_POS2BED } from '../../../modules/nf-core/homer/pos2bed/main' +include { UNZIP } from '../../../modules/nf-core/unzip/main' + +workflow HOMER_PEAKCALLING { + take: + style // val: one of 'factor', 'histone', 'groseq', 'tss', 'dnase', 'super', 'mC' + bam // channel: [ val(meta), path(bam) ] or [] + tagdir // channel: [ val(meta), path(tagdir) ] or [] - if provided, skip makeTagDirectory + fasta // channel: path(fasta) + gtf // channel: path(gtf) or [] + control_bam // channel: [ val(meta), path(control_bam) ] or [] + control_tagdir // channel: [ val(meta), path(control_tagdir) ] or [] + uniqmap // channel: path(uniqmap) or [] + merge_peaks // val: boolean - whether to merge peaks across samples + annotate_individual // val: boolean - whether to annotate individual peak files + quantify_peaks // val: boolean - whether to quantify reads in merged peaks (creates count matrix) + make_bedgraph // val: boolean - whether to create bedGraph files for UCSC visualization + + main: + ch_versions = Channel.empty() + ch_uniqmap = Channel.empty() + + // Handle uniqmap + if (uniqmap) { + if (uniqmap.toString().endsWith('.zip')) { + ch_uniqmap = UNZIP([[:], uniqmap]).unzipped_archive.map { it[1] } + ch_versions = ch_versions.mix(UNZIP.out.versions) + } + else { + ch_uniqmap = uniqmap + } + } + else { + ch_uniqmap = [] + } + + // + // Create or use existing tag directories + // + ch_sample_tagdir = Channel.empty() + ch_control_tagdir = Channel.empty() + + // Create or use sample tag directories + if (tagdir) { + ch_sample_tagdir = tagdir + } else { + HOMER_MAKETAGDIRECTORY_EXP(bam, fasta) + ch_sample_tagdir = HOMER_MAKETAGDIRECTORY_EXP.out.tagdir + ch_versions = ch_versions.mix(HOMER_MAKETAGDIRECTORY_EXP.out.versions.first()) + } + + // Handle control separately + if (control_tagdir) { + ch_control_tagdir = control_tagdir + } else if (control_bam) { + HOMER_MAKETAGDIRECTORY_CNTRL(control_bam, fasta) + ch_control_tagdir = HOMER_MAKETAGDIRECTORY_CNTRL.out.tagdir + ch_versions = ch_versions.mix(HOMER_MAKETAGDIRECTORY_CNTRL.out.versions.first()) + } + + // + // Creating UCSC Visualization Files + // + if ( make_bedgraph ){ + HOMER_MAKEUCSCFILE(ch_sample_tagdir) + ch_versions = ch_versions.mix(HOMER_MAKEUCSCFILE.out.versions.first()) + ch_bedgraph = HOMER_MAKEUCSCFILE.out.bedGraph + + } else { + ch_bedgraph = Channel.empty() + } + + // + // Call peaks with or without control + // + HOMER_FINDPEAKS( + style, + ch_sample_tagdir, + ch_control_tagdir, + ch_uniqmap + ) + ch_versions = ch_versions.mix(HOMER_FINDPEAKS.out.versions.first()) + + // + // Convert peaks to BED format + // + HOMER_POS2BED(HOMER_FINDPEAKS.out.txt) + ch_versions = ch_versions.mix(HOMER_POS2BED.out.versions.first()) + + // + // Annotate individual peaks if requested + // + ch_annotated_individual = Channel.empty() + if (annotate_individual && gtf) { + HOMER_ANNOTATEPEAKS_INDIVIDUAL( + HOMER_FINDPEAKS.out.txt, + fasta, + gtf + ) + ch_annotated_individual = HOMER_ANNOTATEPEAKS_INDIVIDUAL.out.txt + ch_versions = ch_versions.mix(HOMER_ANNOTATEPEAKS_INDIVIDUAL.out.versions.first()) + } + + // + // Merge peaks, annotate, and quantify if requested + // + ch_merged_txt = Channel.empty() + ch_annotated_merged = Channel.empty() + ch_count_matrix = Channel.empty() + + if (merge_peaks) { + // Collect all peak files for merging + ch_all_peaks = HOMER_FINDPEAKS.out.txt + .map { _meta, txt -> txt } + .collect() + .map { peaks -> [[id: 'merged'], peaks] } + + HOMER_MERGEPEAKS(ch_all_peaks) + ch_merged_txt = HOMER_MERGEPEAKS.out.txt + ch_versions = ch_versions.mix(HOMER_MERGEPEAKS.out.versions) + + // Annotate merged peaks (genomic annotation only) + if (gtf) { + HOMER_ANNOTATEPEAKS_MERGED( + HOMER_MERGEPEAKS.out.txt, + fasta, + gtf + ) + ch_annotated_merged = HOMER_ANNOTATEPEAKS_MERGED.out.txt + ch_versions = ch_versions.mix(HOMER_ANNOTATEPEAKS_MERGED.out.versions.first()) + } + + // Quantify reads in merged peaks across all samples (count matrix) + if (quantify_peaks && gtf) { + // Create input for quantification: merged peaks + list of all tag directories + ch_quantify_input = HOMER_MERGEPEAKS.out.txt + .combine( + ch_sample_tagdir + .map { it -> it[1] } + .collect() + .map { tagdirs -> [[id: 'quantification'], tagdirs] } + ) + .map { peak_meta, peaks, _tagdir_meta, tagdirs -> + [peak_meta, peaks, tagdirs] + } + + HOMER_QUANTIFYPEAKS( + ch_quantify_input.map { meta, peaks, _tagdirs -> [meta, peaks] }, + fasta, + gtf + ) + ch_count_matrix = HOMER_QUANTIFYPEAKS.out.txt + ch_versions = ch_versions.mix(HOMER_QUANTIFYPEAKS.out.versions.first()) + } + } + + emit: + tagdir = ch_sample_tagdir // channel: [ val(meta), path(tagdir) ] + bedgraph = ch_bedgraph // channel: [ val(meta), path(bedGraph.gz) ] + txt = HOMER_FINDPEAKS.out.txt // channel: [ val(meta), path(_{regions,peaks,tss,superEnhancers,...}.txt) ] + gtf = HOMER_FINDPEAKS.out.gtf // channel: [ val(meta), path(.gtf) ] . this is only for style = 'groseq' + bed = HOMER_POS2BED.out.bed // channel: [ val(meta), path(_{regions,peaks,tss,superEnhancers,...}.bed) ] + merged_txt = ch_merged_txt // channel: [ val(meta), path(merged.txt) ] or empty + annotated_individual = ch_annotated_individual // channel: [ val(meta), path(annotated.txt) ] or empty + annotated_merged = ch_annotated_merged // channel: [ val(meta), path(annotated.txt) ] or empty + count_matrix = ch_count_matrix // channel: [ val(meta), path(count_matrix.txt) ] or empty + versions = ch_versions // channel: [ versions.yml ] +} diff --git a/subworkflows/nf-core/homer_peakcalling/meta.yml b/subworkflows/nf-core/homer_peakcalling/meta.yml new file mode 100644 index 000000000000..6f0e3635af23 --- /dev/null +++ b/subworkflows/nf-core/homer_peakcalling/meta.yml @@ -0,0 +1,123 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "homer_peakcalling" +description: Peak calling workflow using HOMER for ChIP-seq, ChIP-exo, and other sequencing data with optional peak merging and annotation +keywords: + - peak calling + - chipseq + - chipexo + - homer + - annotation + - merge peaks +components: + - homer/maketagdirectory + - homer/makeucscfile + - homer/findpeaks + - homer/mergepeaks + - homer/annotatepeaks + - homer/pos2bed + - unzip +input: + - bam: + type: file + description: | + Channel containing BAM files for peak calling + Structure: [ val(meta), path(bam) ] + pattern: "*.bam" + - fasta: + type: file + description: | + Reference genome FASTA file + Structure: path(fasta) + pattern: "*.{fa,fasta,fa.gz,fasta.gz}" + - gtf: + type: file + description: | + Gene annotation GTF file for peak annotation. + If an empty channel is passed in, then the subworkflow skips annotation steps. + Structure: path(gtf) + pattern: "*.gtf" + - control: + type: file + description: | + Optional control/input BAM file for peak calling. Can be empty channel. + Structure: [ val(meta), path(bam) ] or empty + pattern: "*.bam" + - uniqmap: + type: file + description: | + Optional uniquely mappable regions file or directory (can be zipped). + Can be empty channel. + Structure: path(uniqmap) or empty + pattern: "*.zip" + - merge_peaks: + type: boolean + description: | + Whether to merge peaks across all samples into a consensus peak set. If a gtf + is passed in via the input, then the merged peaks are annotated + - annotate_individual: + type: boolean + description: | + Whether to annotate individual peak files. If false and merge_peaks is false, + no annotation is performed. If no gtf is passed into the subworkflow, + annotation steps are not performed regardless of this setting. +output: + - tagdir: + type: directory + description: | + HOMER tag directories for each sample + Structure: [ val(meta), path(tagdir) ] + - bedgraph: + type: file + description: | + BedGraph files for UCSC genome browser visualization, created from processed tag directories + Structure: [ val(meta), path(bedGraph.gz) ] + pattern: "*.bedGraph.gz" + - txt: + type: file + description: | + Individual output txt files in HOMER format for each sample + Structure: [ val(meta), path(_{peaks,regions,tss,superEnhancers,...}.txt) ] + The file type (and hence suffix) depends on the `style`. e.g. style = factor + would output *_peaks.txt + pattern: "*.txt" + - bed: + type: file + description: | + Individual txt files converted to BED format + Structure: [ val(meta), path(peaks.bed) ] + pattern: "*.bed" + - gtf: + type: file + description: | + This is only created for style = groseq. A gtf file of the RNA loci inferred + from the experiment + - merged_peaks: + type: file + description: | + Merged consensus peak file in HOMER format (empty if merge_peaks is false) + Structure: [ val(meta), path(merged.txt) ] + pattern: "*.txt" + - annotated_individual: + type: file + description: | + Annotated individual peak files (empty if annotate_individual is false) + Structure: [ val(meta), path(annotated.txt) ] + pattern: "*.txt" + - annotated_merged: + type: file + description: | + Annotated merged peak file (empty if merge_peaks is false) + Structure: [ val(meta), path(annotated.txt) ] + pattern: "*.txt" + - versions: + type: file + description: | + File containing software versions + Structure: [ path(versions.yml) ] + pattern: "versions.yml" +authors: + - "@edmundmiller" + - "@cmatKhan" +maintainers: + - "@edmundmiller" + - "@cmatKhan" diff --git a/subworkflows/nf-core/homer_peakcalling/tests/bed.config b/subworkflows/nf-core/homer_peakcalling/tests/bed.config new file mode 100644 index 000000000000..d3390db87dab --- /dev/null +++ b/subworkflows/nf-core/homer_peakcalling/tests/bed.config @@ -0,0 +1,5 @@ +process { + withName: 'HOMER_PEAKCALLING:HOMER_MAKETAGDIRECTORY' { + ext.args = "-checkGC -format bed -single" + } +} diff --git a/subworkflows/nf-core/homer_peakcalling/tests/main.nf.test b/subworkflows/nf-core/homer_peakcalling/tests/main.nf.test new file mode 100644 index 000000000000..f26e08288585 --- /dev/null +++ b/subworkflows/nf-core/homer_peakcalling/tests/main.nf.test @@ -0,0 +1,392 @@ +nextflow_workflow { + + name "Test Workflow HOMER_PEAKCALLING" + script "../main.nf" + workflow "HOMER_PEAKCALLING" + + tag "subworkflows" + tag "subworkflows_nfcore" + tag "subworkflows/homer_peakcalling" + tag "homer" + tag "unzip" + tag "homer/maketagdirectory" + tag "homer/makeucscfile" + tag "homer/findpeaks" + tag "homer/mergepeaks" + tag "homer/annotatepeaks" + tag "homer/pos2bed" + + test("sarscov2 - bam - no merge, no annotation") { + + when { + workflow { + """ + // style + input[0] = "factor" + // bam + input[1] = Channel.of( + [ [ id: 'sample1' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.single_end.sorted.bam', checkIfExists: true) ], + [ [ id: 'sample2' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) ] + ) + // tagdir + input[2] = [] + // fasta + input[3] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + // gtf + input[4] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.gtf', checkIfExists: true) + // control bam + input[5] = [] + // control tagdir + input[6] = [] + // uniqmap + input[7] = [] + // merge_peaks + input[8] = false + // annotate_individual + input[9] = false + // quantify_peaks + input[10] = false + // make_bedgraph + input[11] = true + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert snapshot( + workflow.out.tagdir, + path(workflow.out.bedgraph.get(0).get(1)).linesGzip.size(), + workflow.out.txt, + workflow.out.gtf, + workflow.out.bed, + workflow.out.merged_txt, + workflow.out.annotated_individual, + workflow.out.annotated_merged, + workflow.out.count_matrix, + path(workflow.out.versions.get(0)).yaml + ).match() } + ) + } + } + + test("sarscov2 - bam - merge only, annotate merged") { + + when { + workflow { + """ + // style + input[0] = "factor" + // bam + input[1] = Channel.of( + [ [ id: 'sample1' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.single_end.sorted.bam', checkIfExists: true) ], + [ [ id: 'sample2' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) ] + ) + // tagdir + input[2] = [] + // fasta + input[3] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + // gtf + input[4] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.gtf', checkIfExists: true) + // control bam + input[5] = [] + // control tagdir + input[6] = [] + // uniqmap + input[7] = [] + // merge_peaks + input[8] = true + // annotate_individual + input[9] = false + // quantify_peaks + input[10] = false + // make_bedgraph + input[11] = true + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert snapshot( + workflow.out.tagdir, + path(workflow.out.bedgraph.get(0).get(1)).linesGzip.size(), + workflow.out.txt, + workflow.out.gtf, + workflow.out.bed, + workflow.out.merged_txt, + workflow.out.annotated_individual, + workflow.out.annotated_merged, + workflow.out.count_matrix, + path(workflow.out.versions.get(0)).yaml + ).match() } + ) + } + } + + test("sarscov2 - bam - no merge, annotate individual") { + + when { + workflow { + """ + // style + input[0] = "factor" + // bam + input[1] = Channel.of( + [ [ id: 'sample1' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.single_end.sorted.bam', checkIfExists: true) ], + [ [ id: 'sample2' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) ] + ) + // tagdir + input[2] = [] + // fasta + input[3] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + // gtf + input[4] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.gtf', checkIfExists: true) + // control bam + input[5] = [] + // control tagdir + input[6] = [] + // uniqmap + input[7] = [] + // merge_peaks + input[8] = false + // annotate_individual + input[9] = true + // quantify_peaks + input[10] = false + // make_bedgraph + input[11] = true + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert snapshot( + workflow.out.tagdir, + path(workflow.out.bedgraph.get(0).get(1)).linesGzip.size(), + workflow.out.txt, + workflow.out.gtf, + workflow.out.bed, + workflow.out.merged_txt, + workflow.out.annotated_individual, + workflow.out.annotated_merged, + workflow.out.count_matrix, + path(workflow.out.versions.get(0)).yaml + ).match() } + ) + } + } + + test("sarscov2 - bam - merge and annotate both, with quantification") { + + when { + workflow { + """ + // style + input[0] = "factor" + // bam + input[1] = Channel.of( + [ [ id: 'sample1' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.single_end.sorted.bam', checkIfExists: true) ], + [ [ id: 'sample2' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) ] + ) + // tagdir + input[2] = [] + // fasta + input[3] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + // gtf + input[4] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.gtf', checkIfExists: true) + // control bam + input[5] = [] + // control tagdir + input[6] = [] + // uniqmap + input[7] = [] + // merge_peaks + input[8] = true + // annotate_individual + input[9] = true + // quantify_peaks + input[10] = true + // make_bedgraph + input[11] = true + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert snapshot( + workflow.out.tagdir, + path(workflow.out.bedgraph.get(0).get(1)).linesGzip.size(), + workflow.out.txt, + workflow.out.gtf, + workflow.out.bed, + workflow.out.merged_txt, + workflow.out.annotated_individual, + workflow.out.annotated_merged, + workflow.out.count_matrix, + path(workflow.out.versions.get(0)).yaml + ).match() } + ) + } + } + + test("sarscov2 - bam with control") { + + when { + workflow { + """ + // style + input[0] = "factor" + // bam + input[1] = Channel.of( + [ [ id: 'sample1' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.single_end.sorted.bam', checkIfExists: true) ], + [ [ id: 'sample2' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) ] + ) + // tagdir + input[2] = [] + // fasta + input[3] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + // gtf + input[4] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.gtf', checkIfExists: true) + // control bam + input[5] = Channel.of( + [ [ id: 'control' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.single_end.sorted.bam', checkIfExists: true) ] + ) + // control tagdir + input[6] = [] + // uniqmap + input[7] = [] + // merge_peaks + input[8] = false + // annotate_individual + input[9] = false + // quantify_peaks + input[10] = false + // make_bedgraph + input[11] = true + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert snapshot( + workflow.out.tagdir, + path(workflow.out.bedgraph.find {it[0].id == "sample1"}[1]).linesGzip.size(), + workflow.out.txt.size(), + workflow.out.bed.size(), + path(workflow.out.versions.get(0)).yaml + ).match() } + ) + } + } + + test("GROseq tutorial files with uniqmap") { + + tag "uniqmap" + config "./bed.config" + + when { + workflow { + """ + // style + input[0] = "groseq" + // bam + input[1] = [ + [ id: 'groseq_test' ], + [ + file('ftp://ftp.ncbi.nlm.nih.gov/geo/samples/GSM340nnn/GSM340901/suppl/GSM340901_lib1_aligned.bed.gz', checkIfExists: true), + file('ftp://ftp.ncbi.nlm.nih.gov/geo/samples/GSM340nnn/GSM340902/suppl/GSM340902_lib2_aligned.bed.gz', checkIfExists: true) + ], + ] + // tagdir + input[2] = [] + // fasta + input[3] = file('https://hgdownload.soe.ucsc.edu/goldenPath/hg18/chromosomes/chr14.fa.gz', checkIfExists: true) + // gtf + input[4] = [] + // control bam + input[5] = [] + // control tagdir + input[6] = [] + // uniqmap + input[7] = file('https://raw.githubusercontent.com/nf-core/test-datasets/nascent/reference/uniqmap.GRCh38_chr21.50nt.zip', checkIfExists: true) + // merge_peaks + input[8] = false + // annotate_individual + input[9] = false + // quantify_peaks + input[10] = false + // make_bedgraph + input[11] = true + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert snapshot( + workflow.out.tagdir.size(), + path(workflow.out.bedgraph.get(0).get(1)).linesGzip.size(), + workflow.out.txt, + workflow.out.gtf, + workflow.out.bed, + path(workflow.out.versions.get(0)).yaml + ).match() } + ) + } + } + + test("sarscov2 - stub") { + + options "-stub" + + when { + workflow { + """ + // style + input[0] = "factor" + // bam + input[1] = Channel.of( + [ [ id: 'sample1' ], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.single_end.sorted.bam', checkIfExists: true) ] + ) + // tagdir + input[2] = [] + // fasta + input[3] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + // gtf + input[4] = file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.gtf', checkIfExists: true) + // control bam + input[5] = [] + // control tagdir + input[6] = [] + // uniqmap + input[7] = [] + // merge_peaks + input[8] = true + // annotate_individual + input[9] = true + // quantify_peaks + input[10] = true + // make_bedgraph + input[11] = true + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out).match() } + ) + } + } +} diff --git a/subworkflows/nf-core/homer_peakcalling/tests/main.nf.test.snap b/subworkflows/nf-core/homer_peakcalling/tests/main.nf.test.snap new file mode 100644 index 000000000000..c807eaa402b1 --- /dev/null +++ b/subworkflows/nf-core/homer_peakcalling/tests/main.nf.test.snap @@ -0,0 +1,430 @@ +{ + "sarscov2 - bam - no merge, no annotation": { + "content": [ + [ + [ + { + "id": "sample1" + }, + [ + "MT192765.1.tags.tsv:md5,33053d18bd0fd84158949874398e3b47", + "tagAutocorrelation.txt:md5,6fbb03c59c1d935992803c18010bed65", + "tagCountDistribution.txt:md5,319bca429feca0f48d42572b75bc5e5d", + "tagInfo.txt:md5,44fa5c3a317d0e2a8b5c2d2b199c6459", + "tagLengthDistribution.txt:md5,cbf27cb12db44a6c9f4b5db4fe2b0780" + ] + ], + [ + { + "id": "sample2" + }, + [ + "MT192765.1.tags.tsv:md5,5d6d914e304c32ac0d9a17ddc645a5f5", + "tagAutocorrelation.txt:md5,09170f8737ce78affd036cfa1167b6a9", + "tagCountDistribution.txt:md5,aa30a86b477684539167a4ad9d7dde4d", + "tagInfo.txt:md5,55f51283a3a34ac275028718784c79bb", + "tagLengthDistribution.txt:md5,ec87f6f0d045b0b8a3c9442cf74b1eb2" + ] + ] + ], + 161, + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + { + "HOMER_PEAKCALLING:HOMER_MAKEUCSCFILE": { + "homer": 5.1 + } + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.7" + }, + "timestamp": "2025-10-06T18:02:06.780388157" + }, + "sarscov2 - stub": { + "content": [ + { + "0": [ + [ + { + "id": "sample1" + }, + [ + "genome.1.tags.tsv:md5,d41d8cd98f00b204e9800998ecf8427e", + "tagAutocorrelation.txt:md5,d41d8cd98f00b204e9800998ecf8427e", + "tagCountDistribution.txt:md5,d41d8cd98f00b204e9800998ecf8427e", + "tagInfo.txt:md5,d41d8cd98f00b204e9800998ecf8427e", + "tagLengthDistribution.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "1": [ + [ + { + "id": "sample1" + }, + "sample1.bedGraph.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "2": [ + + ], + "3": [ + + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + + ], + "7": [ + + ], + "8": [ + + ], + "9": [ + "versions.yml:md5,a08c87d7bebe3e4050cb97ae87843488", + "versions.yml:md5,dba09d1f0c348a3efff432a992c49d64" + ], + "annotated_individual": [ + + ], + "annotated_merged": [ + + ], + "bed": [ + + ], + "bedgraph": [ + [ + { + "id": "sample1" + }, + "sample1.bedGraph.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "count_matrix": [ + + ], + "gtf": [ + + ], + "merged_txt": [ + + ], + "tagdir": [ + [ + { + "id": "sample1" + }, + [ + "genome.1.tags.tsv:md5,d41d8cd98f00b204e9800998ecf8427e", + "tagAutocorrelation.txt:md5,d41d8cd98f00b204e9800998ecf8427e", + "tagCountDistribution.txt:md5,d41d8cd98f00b204e9800998ecf8427e", + "tagInfo.txt:md5,d41d8cd98f00b204e9800998ecf8427e", + "tagLengthDistribution.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "txt": [ + + ], + "versions": [ + "versions.yml:md5,a08c87d7bebe3e4050cb97ae87843488", + "versions.yml:md5,dba09d1f0c348a3efff432a992c49d64" + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.7" + }, + "timestamp": "2025-10-06T18:19:36.497325125" + }, + "sarscov2 - bam - merge only, annotate merged": { + "content": [ + [ + [ + { + "id": "sample1" + }, + [ + "MT192765.1.tags.tsv:md5,33053d18bd0fd84158949874398e3b47", + "tagAutocorrelation.txt:md5,6fbb03c59c1d935992803c18010bed65", + "tagCountDistribution.txt:md5,319bca429feca0f48d42572b75bc5e5d", + "tagInfo.txt:md5,44fa5c3a317d0e2a8b5c2d2b199c6459", + "tagLengthDistribution.txt:md5,cbf27cb12db44a6c9f4b5db4fe2b0780" + ] + ], + [ + { + "id": "sample2" + }, + [ + "MT192765.1.tags.tsv:md5,5d6d914e304c32ac0d9a17ddc645a5f5", + "tagAutocorrelation.txt:md5,09170f8737ce78affd036cfa1167b6a9", + "tagCountDistribution.txt:md5,aa30a86b477684539167a4ad9d7dde4d", + "tagInfo.txt:md5,55f51283a3a34ac275028718784c79bb", + "tagLengthDistribution.txt:md5,ec87f6f0d045b0b8a3c9442cf74b1eb2" + ] + ] + ], + 161, + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + { + "HOMER_PEAKCALLING:HOMER_MAKEUCSCFILE": { + "homer": 5.1 + } + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.7" + }, + "timestamp": "2025-10-06T18:12:39.559587289" + }, + "sarscov2 - bam with control": { + "content": [ + [ + [ + { + "id": "sample1" + }, + [ + "MT192765.1.tags.tsv:md5,33053d18bd0fd84158949874398e3b47", + "tagAutocorrelation.txt:md5,6fbb03c59c1d935992803c18010bed65", + "tagCountDistribution.txt:md5,319bca429feca0f48d42572b75bc5e5d", + "tagInfo.txt:md5,44fa5c3a317d0e2a8b5c2d2b199c6459", + "tagLengthDistribution.txt:md5,cbf27cb12db44a6c9f4b5db4fe2b0780" + ] + ], + [ + { + "id": "sample2" + }, + [ + "MT192765.1.tags.tsv:md5,5d6d914e304c32ac0d9a17ddc645a5f5", + "tagAutocorrelation.txt:md5,09170f8737ce78affd036cfa1167b6a9", + "tagCountDistribution.txt:md5,aa30a86b477684539167a4ad9d7dde4d", + "tagInfo.txt:md5,55f51283a3a34ac275028718784c79bb", + "tagLengthDistribution.txt:md5,ec87f6f0d045b0b8a3c9442cf74b1eb2" + ] + ] + ], + 161, + 1, + [ + [ + { + "id": "sample1" + }, + "sample1.bed:md5,de827b12513fe89f6248ea6539f8d052" + ] + ], + { + "HOMER_PEAKCALLING:HOMER_MAKEUCSCFILE": { + "homer": 5.1 + } + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.7" + }, + "timestamp": "2025-10-07T10:36:39.116331148" + }, + "sarscov2 - bam - no merge, annotate individual": { + "content": [ + [ + [ + { + "id": "sample1" + }, + [ + "MT192765.1.tags.tsv:md5,33053d18bd0fd84158949874398e3b47", + "tagAutocorrelation.txt:md5,6fbb03c59c1d935992803c18010bed65", + "tagCountDistribution.txt:md5,319bca429feca0f48d42572b75bc5e5d", + "tagInfo.txt:md5,44fa5c3a317d0e2a8b5c2d2b199c6459", + "tagLengthDistribution.txt:md5,cbf27cb12db44a6c9f4b5db4fe2b0780" + ] + ], + [ + { + "id": "sample2" + }, + [ + "MT192765.1.tags.tsv:md5,5d6d914e304c32ac0d9a17ddc645a5f5", + "tagAutocorrelation.txt:md5,09170f8737ce78affd036cfa1167b6a9", + "tagCountDistribution.txt:md5,aa30a86b477684539167a4ad9d7dde4d", + "tagInfo.txt:md5,55f51283a3a34ac275028718784c79bb", + "tagLengthDistribution.txt:md5,ec87f6f0d045b0b8a3c9442cf74b1eb2" + ] + ] + ], + 161, + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + { + "HOMER_PEAKCALLING:HOMER_MAKEUCSCFILE": { + "homer": 5.1 + } + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.7" + }, + "timestamp": "2025-10-06T18:12:45.049256496" + }, + "sarscov2 - bam - merge and annotate both, with quantification": { + "content": [ + [ + [ + { + "id": "sample1" + }, + [ + "MT192765.1.tags.tsv:md5,33053d18bd0fd84158949874398e3b47", + "tagAutocorrelation.txt:md5,6fbb03c59c1d935992803c18010bed65", + "tagCountDistribution.txt:md5,319bca429feca0f48d42572b75bc5e5d", + "tagInfo.txt:md5,44fa5c3a317d0e2a8b5c2d2b199c6459", + "tagLengthDistribution.txt:md5,cbf27cb12db44a6c9f4b5db4fe2b0780" + ] + ], + [ + { + "id": "sample2" + }, + [ + "MT192765.1.tags.tsv:md5,5d6d914e304c32ac0d9a17ddc645a5f5", + "tagAutocorrelation.txt:md5,09170f8737ce78affd036cfa1167b6a9", + "tagCountDistribution.txt:md5,aa30a86b477684539167a4ad9d7dde4d", + "tagInfo.txt:md5,55f51283a3a34ac275028718784c79bb", + "tagLengthDistribution.txt:md5,ec87f6f0d045b0b8a3c9442cf74b1eb2" + ] + ] + ], + 161, + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + { + "HOMER_PEAKCALLING:HOMER_MAKEUCSCFILE": { + "homer": 5.1 + } + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.7" + }, + "timestamp": "2025-10-06T18:12:50.636045964" + }, + "GROseq tutorial files with uniqmap": { + "content": [ + 1, + 15368355, + [ + + ], + [ + + ], + [ + + ], + { + "HOMER_PEAKCALLING:HOMER_MAKEUCSCFILE": { + "homer": 5.1 + } + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.7" + }, + "timestamp": "2025-10-07T10:29:31.678945195" + } +} \ No newline at end of file