diff --git a/.nf-core.yml b/.nf-core.yml
index b4b7d5a8..3ea7e386 100644
--- a/.nf-core.yml
+++ b/.nf-core.yml
@@ -41,4 +41,4 @@ template:
skip_features:
- fastqc
- is_nfcore
- version: 1.13.6
+ version: 1.14.0dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd27c002..ac861fa8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,23 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## v1.14.0dev
+
+### New features
+
+- Added a new caller: `GATK4_MUTECT2` followed by `GATK4_FILTERMUTECTCALLS`. Pass `mutect2` to the `--callers` parameter to use it.
+
+### Changes
+
+- Check that the VCF contains enough variants before running automap (it needs to have at least 10000 variants)
+
+### Parameters
+
+| Old | New |
+| --- | ------------------------ |
+| | `--panel_of_normals` |
+| | `--panel_of_normals_tbi` |
+
## v1.13.6
- Revert the default configs base to the nf-core configs in preparation of converting nf-cmgg/configs to a private repo
diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml
index 0bd23247..2771c125 100644
--- a/assets/multiqc_config.yml
+++ b/assets/multiqc_config.yml
@@ -1,5 +1,5 @@
report_comment: >
- This report has been generated by the nf-cmgg/smallvariants analysis pipeline.
+ This report has been generated by the nf-cmgg/smallvariants analysis pipeline.
report_section_order:
"nf-cmgg-smallvariants-methods-description":
order: -1000
diff --git a/conf/modules.config b/conf/modules.config
index 1cc3aff5..ce84f384 100644
--- a/conf/modules.config
+++ b/conf/modules.config
@@ -72,11 +72,11 @@ process {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
- withName: "^.*CRAM_CALL_GATK4:GATK4_CALIBRATEDRAGSTRMODEL\$" {
+ withName: "^.*CRAM_CALL_HAPLOTYPECALLER:GATK4_CALIBRATEDRAGSTRMODEL\$" {
ext.args = "--parallel"
}
- withName: "^.*CRAM_CALL_GATK4:GATK4_HAPLOTYPECALLER\$" {
+ withName: "^.*CRAM_CALL_HAPLOTYPECALLER:GATK4_HAPLOTYPECALLER\$" {
time = { 16.h * task.attempt }
ext.prefix = {"${meta.id}.g"}
ext.args = {
@@ -91,12 +91,12 @@ process {
}
}
- withName: "^.*CRAM_CALL_GATK4:VCF_CONCAT_BCFTOOLS:BCFTOOLS_CONCAT\$" {
+ withName: "^.*CRAM_CALL_HAPLOTYPECALLER:VCF_CONCAT_BCFTOOLS:BCFTOOLS_CONCAT\$" {
ext.prefix = { "${meta.id}.${meta.caller}.g" }
ext.args = '--allow-overlaps --output-type z --write-index=tbi'
}
- withName: "^.*CRAM_CALL_GATK4:BCFTOOLS_STATS\$" {
+ withName: "^.*CRAM_CALL_HAPLOTYPECALLER:BCFTOOLS_STATS\$" {
ext.prefix = { "${meta.id}.${meta.caller}" }
}
@@ -204,6 +204,44 @@ process {
ext.prefix = {"${meta.id}.concat"}
}
+ /*
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ MUTECT2
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+ withName: "^.*CRAM_CALL_MUTECT2:GATK4_MUTECT2\$" {
+ time = { 16.h * task.attempt }
+ ext.args = [
+ "--annotation ClippingRankSumTest",
+ "--annotation DepthPerSampleHC",
+ "--annotation MappingQualityRankSumTest",
+ "--annotation MappingQualityZero",
+ "--annotation QualByDepth",
+ "--annotation ReadPosRankSumTest",
+ "--annotation RMSMappingQuality",
+ "--annotation FisherStrand",
+ "--annotation MappingQuality",
+ "--annotation DepthPerAlleleBySample",
+ "--annotation Coverage",
+ "--read-validation-stringency LENIENT",
+ "--interval-set-rule INTERSECTION",
+ "--max-reads-per-alignment-start 0",
+ "--initial-tumor-lod 0",
+ "--tumor-lod-to-emit 0",
+ "--min-base-quality-score 20"
+ ].join(" ")
+ }
+
+ withName: "^.*CRAM_CALL_MUTECT2:GATK4_FILTERMUTECTCALLS\$" {
+ ext.prefix = {"${meta.id}.filtered"}
+ }
+
+ withName: "^.*CRAM_CALL_MUTECT2:VCF_CONCAT_BCFTOOLS:BCFTOOLS_CONCAT\$" {
+ ext.args = '--allow-overlaps --output-type z --write-index=tbi'
+ ext.prefix = {"${meta.id}.concat"}
+ }
+
/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FILTER
diff --git a/main.nf b/main.nf
index 9b874826..50e1c7f5 100644
--- a/main.nf
+++ b/main.nf
@@ -318,6 +318,12 @@ params {
// A semicolon-seperated list of resource files for VCFanno, please also supply their indices using this parameter.
vcfanno_resources: String? = getGenomeAttribute('vcfanno_resources', params.genomes, params.genome)
+
+ // Path to the panel of normals VCF file.
+ panel_of_normals: Path? = getGenomeAttribute('panel_of_normals', params.genomes, params.genome)
+
+ // Path to the index of the panel of normals VCF file.
+ panel_of_normals_tbi: Path? = getGenomeAttribute('panel_of_normals_tbi', params.genomes, params.genome)
}
workflow {
@@ -333,12 +339,16 @@ workflow {
// Check for dependencies between parameters
//
- def List available_callers = ["haplotypecaller", "vardict", "elprep"]
+ def List available_callers = ["haplotypecaller", "vardict", "elprep", "mutect2"]
if(params.dbsnp_tbi && !params.dbsnp){
error("Please specify the dbsnp VCF with --dbsnp VCF")
}
+ if(params.panel_of_normals_tbi && !params.panel_of_normals){
+ error("Please specify the panel of normals VCF with --panel_of_normals VCF")
+ }
+
if (params.annotate) {
// Check if a genome is given
if (!params.genome) { error("A genome should be supplied for annotation (use --genome)") }
@@ -358,7 +368,7 @@ workflow {
def callers = params.callers.tokenize(",")
callers.each { caller ->
- if(!(caller in available_callers)) { error("\"${caller}\" is not a supported callers please use one or more of these instead: ${available_callers.join(', ')}") }
+ if(!(caller in available_callers)) { error("\"${caller}\" is not a supported caller please use one or more of these instead: ${available_callers.join(', ')}") }
}
/*
@@ -432,6 +442,8 @@ workflow {
params.elsites,
params.msi_baseline,
params.updio_regions,
+ params.panel_of_normals,
+ params.panel_of_normals_tbi,
// Boolean inputs
params.dragstr,
diff --git a/modules.json b/modules.json
index b0708491..81d3d86d 100644
--- a/modules.json
+++ b/modules.json
@@ -102,6 +102,11 @@
"git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120",
"installed_by": ["modules"]
},
+ "gatk4/filtermutectcalls": {
+ "branch": "master",
+ "git_sha": "d5de7a949aa84689f4098c958f05733a6c3804f5",
+ "installed_by": ["modules"]
+ },
"gatk4/genomicsdbimport": {
"branch": "master",
"git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120",
@@ -117,6 +122,11 @@
"git_sha": "b73338eca19d798eb0ef6ed112ef4d27a30d2871",
"installed_by": ["modules"]
},
+ "gatk4/mutect2": {
+ "branch": "master",
+ "git_sha": "6ef220fd9252b42fb3c50348bbdbcb6246730686",
+ "installed_by": ["modules"]
+ },
"gawk": {
"branch": "master",
"git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120",
diff --git a/modules/nf-core/gatk4/filtermutectcalls/environment.yml b/modules/nf-core/gatk4/filtermutectcalls/environment.yml
new file mode 100644
index 00000000..84f68508
--- /dev/null
+++ b/modules/nf-core/gatk4/filtermutectcalls/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/gatk4-main
+ - bioconda::gatk4-main=4.7.0.0
+ # renovate: datasource=conda depName=bioconda/gcnvkernel
+ - bioconda::gcnvkernel=0.9
diff --git a/modules/nf-core/gatk4/filtermutectcalls/main.nf b/modules/nf-core/gatk4/filtermutectcalls/main.nf
new file mode 100644
index 00000000..4f33e1c5
--- /dev/null
+++ b/modules/nf-core/gatk4/filtermutectcalls/main.nf
@@ -0,0 +1,62 @@
+process GATK4_FILTERMUTECTCALLS {
+ tag "${meta.id}"
+ label 'process_low'
+
+ conda "${moduleDir}/environment.yml"
+ container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container
+ ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/b9/b9822b92da68a3e7916072218082e3fa79bebc2f377947c363613adeecd56ec5/data'
+ : 'community.wave.seqera.io/library/gatk4-main_gcnvkernel:961440660027ec01'}"
+
+ input:
+ tuple val(meta), path(vcf), path(vcf_tbi), path(stats), path(orientationbias), path(segmentation), path(table), val(estimate)
+ tuple val(meta2), path(fasta)
+ tuple val(meta3), path(fai)
+ tuple val(meta4), path(dict)
+
+ output:
+ tuple val(meta), path("*.vcf.gz"), emit: vcf
+ tuple val(meta), path("*.vcf.gz.tbi"), emit: tbi
+ tuple val(meta), path("*.filteringStats.tsv"), emit: stats
+ tuple val("${task.process}"), val('gatk4'), eval("gatk --version | sed -n '/GATK.*v/s/.*v//p'"), topic: versions, emit: versions_gatk4
+
+ when:
+ task.ext.when == null || task.ext.when
+
+ script:
+ def args = task.ext.args ?: ''
+ def prefix = task.ext.prefix ?: "${meta.id}"
+
+ def orientationbias_command = orientationbias ? orientationbias.collect { orientationbias_ -> "--orientation-bias-artifact-priors ${orientationbias_}" }.join(' ') : ''
+ def segmentation_command = segmentation ? segmentation.collect { segmentation_ -> "--tumor-segmentation ${segmentation_}" }.join(' ') : ''
+ def estimate_command = estimate ? " --contamination-estimate ${estimate} " : ''
+ def table_command = table ? table.collect { table_ -> "--contamination-table ${table_}" }.join(' ') : ''
+
+ def avail_mem = 3072
+ if (!task.memory) {
+ log.info('[GATK FilterMutectCalls] Available memory not known - defaulting to 3GB. Specify process memory requirements to change this.')
+ }
+ else {
+ avail_mem = (task.memory.mega * 0.8).intValue()
+ }
+ """
+ gatk --java-options "-Xmx${avail_mem}M -XX:-UsePerfData" \\
+ FilterMutectCalls \\
+ --variant ${vcf} \\
+ --output ${prefix}.vcf.gz \\
+ --reference ${fasta} \\
+ ${orientationbias_command} \\
+ ${segmentation_command} \\
+ ${estimate_command} \\
+ ${table_command} \\
+ --tmp-dir . \\
+ ${args}
+ """
+
+ stub:
+ def prefix = task.ext.prefix ?: "${meta.id}"
+ """
+ echo "" | gzip > ${prefix}.vcf.gz
+ touch ${prefix}.vcf.gz.tbi
+ touch ${prefix}.vcf.gz.filteringStats.tsv
+ """
+}
diff --git a/modules/nf-core/gatk4/filtermutectcalls/meta.yml b/modules/nf-core/gatk4/filtermutectcalls/meta.yml
new file mode 100644
index 00000000..eb3e9baf
--- /dev/null
+++ b/modules/nf-core/gatk4/filtermutectcalls/meta.yml
@@ -0,0 +1,161 @@
+name: gatk4_filtermutectcalls
+description: |
+ Filters the raw output of mutect2, can optionally use outputs of calculatecontamination and learnreadorientationmodel to improve filtering.
+keywords:
+ - filtermutectcalls
+ - filter
+ - gatk4
+ - mutect2
+ - vcf
+tools:
+ - gatk4:
+ description: |
+ Developed in the Data Sciences Platform at the Broad Institute, the toolkit offers a wide variety of tools
+ with a primary focus on variant discovery and genotyping. Its powerful processing engine
+ and high-performance computing features make it capable of taking on projects of any size.
+ homepage: https://gatk.broadinstitute.org/hc/en-us
+ documentation: https://gatk.broadinstitute.org/hc/en-us/categories/360002369672s
+ doi: 10.1158/1538-7445.AM2017-3590
+ identifier: ""
+input:
+ - - meta:
+ type: map
+ description: |
+ Groovy Map containing sample information
+ e.g. [ id:'test' ]
+ - vcf:
+ type: file
+ description: compressed vcf file of mutect2calls
+ pattern: "*.vcf.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ - vcf_tbi:
+ type: file
+ description: Tabix index of vcf file
+ pattern: "*vcf.gz.tbi"
+ ontologies: []
+ - stats:
+ type: file
+ description: Stats file that pairs with output vcf file
+ pattern: "*vcf.gz.stats"
+ ontologies: []
+ - orientationbias:
+ type: file
+ description: files containing artifact priors for input vcf. Optional input.
+ pattern: "*.artifact-prior.tar.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ - segmentation:
+ type: file
+ description: tables containing segmentation information for input vcf. Optional
+ input.
+ pattern: "*.segmentation.table"
+ ontologies: []
+ - table:
+ type: file
+ description: table(s) containing contamination data for input vcf. Optional
+ input, takes priority over estimate.
+ pattern: "*.contamination.table"
+ ontologies: []
+ - estimate:
+ type: float
+ description: estimation of contamination value as a double. Optional input,
+ will only be used if table is not specified.
+ - - meta2:
+ type: map
+ description: |
+ Groovy Map containing reference information
+ e.g. [ id:'genome' ]
+ - fasta:
+ type: file
+ description: The reference fasta file
+ pattern: "*.fasta"
+ ontologies: []
+ - - meta3:
+ type: map
+ description: |
+ Groovy Map containing reference information
+ e.g. [ id:'genome' ]
+ - fai:
+ type: file
+ description: Index of reference fasta file
+ pattern: "*.fasta.fai"
+ ontologies: []
+ - - meta4:
+ type: map
+ description: |
+ Groovy Map containing reference information
+ e.g. [ id:'genome' ]
+ - dict:
+ type: file
+ description: GATK sequence dictionary
+ pattern: "*.dict"
+ ontologies: []
+output:
+ vcf:
+ - - meta:
+ type: file
+ description: file containing filtered mutect2 calls.
+ pattern: "*.vcf.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ - "*.vcf.gz":
+ type: file
+ description: file containing filtered mutect2 calls.
+ pattern: "*.vcf.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ tbi:
+ - - meta:
+ type: file
+ description: file containing filtered mutect2 calls.
+ pattern: "*.vcf.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ - "*.vcf.gz.tbi":
+ type: file
+ description: tbi file that pairs with vcf.
+ pattern: "*.vcf.gz.tbi"
+ ontologies: []
+ stats:
+ - - meta:
+ type: file
+ description: file containing filtered mutect2 calls.
+ pattern: "*.vcf.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ - "*.filteringStats.tsv":
+ type: file
+ description: file containing statistics of the filtermutectcalls run.
+ pattern: "*.filteringStats.tsv"
+ ontologies:
+ - edam: http://edamontology.org/format_3475 # TSV
+ versions_gatk4:
+ - - ${task.process}:
+ type: string
+ description: The name of the process
+ - gatk4:
+ type: string
+ description: The name of the tool
+ - gatk --version | sed -n '/GATK.*v/s/.*v//p':
+ type: eval
+ description: The expression to obtain the version of the tool
+topics:
+ versions:
+ - - ${task.process}:
+ type: string
+ description: The name of the process
+ - gatk4:
+ type: string
+ description: The name of the tool
+ - gatk --version | sed -n '/GATK.*v/s/.*v//p':
+ type: eval
+ description: The expression to obtain the version of the tool
+authors:
+ - "@GCJMackenzie"
+ - "@maxulysse"
+ - "@ramprasadn"
+maintainers:
+ - "@GCJMackenzie"
+ - "@maxulysse"
+ - "@ramprasadn"
diff --git a/modules/nf-core/gatk4/filtermutectcalls/tests/main.nf.test b/modules/nf-core/gatk4/filtermutectcalls/tests/main.nf.test
new file mode 100644
index 00000000..64007fc1
--- /dev/null
+++ b/modules/nf-core/gatk4/filtermutectcalls/tests/main.nf.test
@@ -0,0 +1,178 @@
+nextflow_process {
+
+ name "Test Process GATK4_FILTERMUTECTCALLS"
+ script "../main.nf"
+ process "GATK4_FILTERMUTECTCALLS"
+ config "./nextflow.config"
+
+ tag "modules"
+ tag "modules_nfcore"
+ tag "gatk4"
+ tag "gatk4/filtermutectcalls"
+
+ test("human - vcf - base") {
+
+ when {
+ process {
+ """
+ input[0] = [
+ [ id:'test'], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz.tbi', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz.stats', checkIfExists: true),
+ [],
+ [],
+ [],
+ []
+ ]
+
+ input[1] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)
+ ]
+ input[3] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ """
+ }
+ }
+
+ then {
+ assertAll(
+ { assert process.success },
+ { assert snapshot(
+ process.out.findAll { key, val -> key.startsWith("versions") },
+ path(process.out.vcf[0][1]).vcf.variantsMD5,
+ path(process.out.tbi[0][1]).linesGzip.toString().contains("TBI"),
+ file(process.out.stats[0][1]).readLines()[0]
+ ).match() }
+ )
+ }
+
+ }
+
+ test("human - vcf - with-files") {
+
+ when {
+ process {
+ """
+ input[0] = [
+ [ id:'test'], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz.tbi', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz.stats', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/test_test2_paired_mutect2_calls.artifact-prior.tar.gz', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/test_test2_paired.segmentation.table', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/test_test2_paired.contamination.table', checkIfExists: true),
+ []
+ ]
+
+ input[1] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)
+ ]
+ input[3] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ """
+ }
+ }
+
+ then {
+ assertAll(
+ { assert process.success },
+ { assert snapshot(
+ process.out.findAll { key, val -> key.startsWith("versions") },
+ path(process.out.vcf[0][1]).vcf.variantsMD5,
+ path(process.out.tbi[0][1]).linesGzip.toString().contains("TBI"),
+ file(process.out.stats[0][1]).readLines()[0..5]
+ ).match() }
+ )
+ }
+ }
+
+ test("human - vcf - use-val") {
+
+ when {
+ process {
+ """
+ input[0] = [
+ [ id:'test'], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz.tbi', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz.stats', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/test_test2_paired_mutect2_calls.artifact-prior.tar.gz', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/test_test2_paired.segmentation.table', checkIfExists: true),
+ [],
+ '20.0'
+ ]
+
+ input[1] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)
+ ]
+ input[3] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ """
+ }
+ }
+
+ then {
+ assertAll(
+ { assert process.success },
+ { assert snapshot(
+ process.out.findAll { key, val -> key.startsWith("versions") },
+ path(process.out.vcf[0][1]).vcf.variantsMD5,
+ path(process.out.tbi[0][1]).linesGzip.toString().contains("TBI"),
+ file(process.out.stats[0][1]).readLines()[0]
+ ).match() }
+ )
+ }
+ }
+
+ test("human - vcf - stub") {
+
+ options "-stub"
+
+ when {
+ process {
+ """
+ input[0] = [
+ [ id:'test'], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz.tbi', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz.stats', checkIfExists: true),
+ [],
+ [],
+ [],
+ []
+ ]
+
+ input[1] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)
+ ]
+ input[3] = [ [ id:'genome' ], // meta map
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ """
+ }
+ }
+
+ then {
+ assertAll(
+ { assert process.success },
+ { assert snapshot(process.out).match() }
+ )
+ }
+ }
+}
diff --git a/modules/nf-core/gatk4/filtermutectcalls/tests/main.nf.test.snap b/modules/nf-core/gatk4/filtermutectcalls/tests/main.nf.test.snap
new file mode 100644
index 00000000..fc598755
--- /dev/null
+++ b/modules/nf-core/gatk4/filtermutectcalls/tests/main.nf.test.snap
@@ -0,0 +1,145 @@
+{
+ "human - vcf - use-val": {
+ "content": [
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_FILTERMUTECTCALLS",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ },
+ "4f8cfebe28e5fd097a7bfc2e556983d3",
+ true,
+ "#Ln prior of deletion of length 10=-20.72326583694641"
+ ],
+ "timestamp": "2026-08-18T11:17:58.502348",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "human - vcf - stub": {
+ "content": [
+ {
+ "0": [
+ [
+ {
+ "id": "test"
+ },
+ "test.filtered.vcf.gz:md5,68b329da9893e34099c7d8ad5cb9c940"
+ ]
+ ],
+ "1": [
+ [
+ {
+ "id": "test"
+ },
+ "test.filtered.vcf.gz.tbi:md5,d41d8cd98f00b204e9800998ecf8427e"
+ ]
+ ],
+ "2": [
+ [
+ {
+ "id": "test"
+ },
+ "test.filtered.vcf.gz.filteringStats.tsv:md5,d41d8cd98f00b204e9800998ecf8427e"
+ ]
+ ],
+ "3": [
+ [
+ "GATK4_FILTERMUTECTCALLS",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ],
+ "stats": [
+ [
+ {
+ "id": "test"
+ },
+ "test.filtered.vcf.gz.filteringStats.tsv:md5,d41d8cd98f00b204e9800998ecf8427e"
+ ]
+ ],
+ "tbi": [
+ [
+ {
+ "id": "test"
+ },
+ "test.filtered.vcf.gz.tbi:md5,d41d8cd98f00b204e9800998ecf8427e"
+ ]
+ ],
+ "vcf": [
+ [
+ {
+ "id": "test"
+ },
+ "test.filtered.vcf.gz:md5,68b329da9893e34099c7d8ad5cb9c940"
+ ]
+ ],
+ "versions_gatk4": [
+ [
+ "GATK4_FILTERMUTECTCALLS",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T11:18:14.487412",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "human - vcf - with-files": {
+ "content": [
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_FILTERMUTECTCALLS",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ },
+ "54e439a79e4b6956a7f2c5b0730c9918",
+ true,
+ [
+ "#Ln prior of deletion of length 10=-20.72326583694641",
+ "#Ln prior of deletion of length 9=-20.72326583694641",
+ "#Ln prior of deletion of length 8=-20.72326583694641",
+ "#Ln prior of deletion of length 7=-20.72326583694641",
+ "#Ln prior of deletion of length 6=-20.72326583694641",
+ "#Ln prior of deletion of length 5=-20.72326583694641"
+ ]
+ ],
+ "timestamp": "2026-08-18T11:17:37.331961",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "human - vcf - base": {
+ "content": [
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_FILTERMUTECTCALLS",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ },
+ "5352aa0f3ea986008a2652eba7c0fdba",
+ true,
+ "#Ln prior of deletion of length 10=-20.72326583694641"
+ ],
+ "timestamp": "2026-08-18T11:17:14.332579",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/nf-core/gatk4/filtermutectcalls/tests/nextflow.config b/modules/nf-core/gatk4/filtermutectcalls/tests/nextflow.config
new file mode 100644
index 00000000..12fa58fb
--- /dev/null
+++ b/modules/nf-core/gatk4/filtermutectcalls/tests/nextflow.config
@@ -0,0 +1,5 @@
+process {
+ withName: GATK4_FILTERMUTECTCALLS {
+ ext.prefix = { "${meta.id}.filtered" }
+ }
+}
diff --git a/modules/nf-core/gatk4/mutect2/environment.yml b/modules/nf-core/gatk4/mutect2/environment.yml
new file mode 100644
index 00000000..84f68508
--- /dev/null
+++ b/modules/nf-core/gatk4/mutect2/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/gatk4-main
+ - bioconda::gatk4-main=4.7.0.0
+ # renovate: datasource=conda depName=bioconda/gcnvkernel
+ - bioconda::gcnvkernel=0.9
diff --git a/modules/nf-core/gatk4/mutect2/main.nf b/modules/nf-core/gatk4/mutect2/main.nf
new file mode 100644
index 00000000..98cef567
--- /dev/null
+++ b/modules/nf-core/gatk4/mutect2/main.nf
@@ -0,0 +1,70 @@
+process GATK4_MUTECT2 {
+ tag "${meta.id}"
+ label 'process_low'
+
+ conda "${moduleDir}/environment.yml"
+ container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container
+ ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/b9/b9822b92da68a3e7916072218082e3fa79bebc2f377947c363613adeecd56ec5/data'
+ : 'community.wave.seqera.io/library/gatk4-main_gcnvkernel:961440660027ec01'}"
+
+ input:
+ tuple val(meta), path(input), path(input_index), path(intervals)
+ tuple val(meta2), path(fasta)
+ tuple val(meta3), path(fai), path(gzi)
+ tuple val(meta4), path(dict)
+ path alleles
+ path alleles_tbi
+ path germline_resource
+ path germline_resource_tbi
+ path panel_of_normals
+ path panel_of_normals_tbi
+
+ output:
+ tuple val(meta), path("${prefix}.vcf.gz"), emit: vcf
+ tuple val(meta), path("${prefix}.vcf.gz.stats"), emit: stats
+ tuple val(meta), path("${prefix}.vcf.gz.tbi"), emit: tbi
+ tuple val(meta), path("${prefix}.f1r2.tar.gz"), emit: f1r2, optional: true
+ tuple val("${task.process}"), val('gatk4'), eval("gatk --version | sed -n '/GATK.*v/s/.*v//p'"), topic: versions, emit: versions_gatk4
+
+ when:
+ task.ext.when == null || task.ext.when
+
+ script:
+ def args = task.ext.args ?: ''
+ prefix = task.ext.prefix ?: "${meta.id}"
+ def inputs = input.collect { vcf_ -> "--input ${vcf_}" }.join(" ")
+ def interval_command = intervals ? "--intervals ${intervals}" : ""
+ def pon_command = panel_of_normals ? "--panel-of-normals ${panel_of_normals}" : ""
+ def gr_command = germline_resource ? "--germline-resource ${germline_resource}" : ""
+ def a_command = alleles ? "--alleles ${alleles}" : ""
+
+ def avail_mem = 3072
+ if (!task.memory) {
+ log.info('[GATK Mutect2] Available memory not known - defaulting to 3GB. Specify process memory requirements to change this.')
+ }
+ else {
+ avail_mem = (task.memory.mega * 0.8).intValue()
+ }
+ """
+ gatk --java-options "-Xmx${avail_mem}M -XX:-UsePerfData" \\
+ Mutect2 \\
+ ${inputs} \\
+ --output ${prefix}.vcf.gz \\
+ --reference ${fasta} \\
+ ${pon_command} \\
+ ${gr_command} \\
+ ${a_command} \\
+ ${interval_command} \\
+ --tmp-dir . \\
+ ${args}
+ """
+
+ stub:
+ prefix = task.ext.prefix ?: "${meta.id}"
+ """
+ echo "" | gzip > ${prefix}.vcf.gz
+ touch ${prefix}.vcf.gz.tbi
+ touch ${prefix}.vcf.gz.stats
+ echo "" | gzip > ${prefix}.f1r2.tar.gz
+ """
+}
diff --git a/modules/nf-core/gatk4/mutect2/meta.yml b/modules/nf-core/gatk4/mutect2/meta.yml
new file mode 100644
index 00000000..adac5cde
--- /dev/null
+++ b/modules/nf-core/gatk4/mutect2/meta.yml
@@ -0,0 +1,175 @@
+name: gatk4_mutect2
+description: Call somatic SNVs and indels via local assembly of haplotypes.
+keywords:
+ - gatk4
+ - haplotype
+ - indels
+ - mutect2
+ - snvs
+ - somatic
+tools:
+ - gatk4:
+ description: |
+ Developed in the Data Sciences Platform at the Broad Institute, the toolkit offers a wide variety of tools
+ with a primary focus on variant discovery and genotyping. Its powerful processing engine
+ and high-performance computing features make it capable of taking on projects of any size.
+ homepage: https://gatk.broadinstitute.org/hc/en-us
+ documentation: https://gatk.broadinstitute.org/hc/en-us/categories/360002369672s
+ doi: 10.1158/1538-7445.AM2017-3590
+ licence: ["Apache-2.0"]
+ identifier: ""
+input:
+ - - meta:
+ type: map
+ description: |
+ Groovy Map containing sample information
+ e.g. [ id:'test']
+ - input:
+ type: list
+ description: list of BAM files, also able to take CRAM as an input
+ pattern: "*.{bam/cram}"
+ - input_index:
+ type: list
+ description: list of BAM file indexes, also able to take CRAM indexes as an
+ input
+ pattern: "*.{bam.bai/cram.crai}"
+ - intervals:
+ type: file
+ description: Specify region the tools is run on.
+ pattern: ".{bed,interval_list}"
+ ontologies: []
+ - - meta2:
+ type: map
+ description: |
+ Groovy Map containing reference information
+ e.g. [ id:'genome' ]
+ - fasta:
+ type: file
+ description: The reference fasta file
+ pattern: "*.{fasta,fasta.gz}"
+ ontologies: []
+ - - meta3:
+ type: map
+ description: |
+ Groovy Map containing reference information
+ e.g. [ id:'genome' ]
+ - fai:
+ type: file
+ description: Index of reference fasta file
+ pattern: "*.{fasta.fai,fasta.fai.gz}"
+ ontologies: []
+ - gzi:
+ type: file
+ description: Index of bgzipped reference fasta file
+ pattern: "*.fasta.gz.gzi"
+ ontologies: []
+ - - meta4:
+ type: map
+ description: |
+ Groovy Map containing reference information
+ e.g. [ id:'genome' ]
+ - dict:
+ type: file
+ description: GATK sequence dictionary
+ pattern: "*.dict"
+ ontologies: []
+ - alleles:
+ type: file
+ description: vcf file to be used to force-call alleles.
+ pattern: "*.vcf.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ - alleles_tbi:
+ type: file
+ description: Index file for alleles to be force-called.
+ pattern: "*.vcf.gz.tbi"
+ ontologies: []
+ - germline_resource:
+ type: file
+ description: Population vcf of germline sequencing, containing allele fractions.
+ pattern: "*.vcf.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ - germline_resource_tbi:
+ type: file
+ description: Index file for the germline resource.
+ pattern: "*.vcf.gz.tbi"
+ ontologies: []
+ - panel_of_normals:
+ type: file
+ description: vcf file to be used as a panel of normals.
+ pattern: "*.vcf.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ - panel_of_normals_tbi:
+ type: file
+ description: Index for the panel of normals.
+ pattern: "*.vcf.gz.tbi"
+ ontologies: []
+output:
+ vcf:
+ - - meta:
+ type: map
+ description: A Groovy map containing sample information
+ - "${prefix}.vcf.gz":
+ type: file
+ description: compressed vcf file
+ pattern: "${prefix}.vcf.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ stats:
+ - - meta:
+ type: map
+ description: A Groovy map containing sample information
+ - "${prefix}.vcf.gz.stats":
+ type: file
+ description: Stats file that pairs with output vcf file
+ pattern: "${prefix}.vcf.gz.stats"
+ ontologies: []
+ tbi:
+ - - meta:
+ type: map
+ description: A Groovy map containing sample information
+ - "${prefix}.vcf.gz.tbi":
+ type: file
+ description: Index of vcf file
+ pattern: "${prefix}.vcf.gz.tbi"
+ ontologies: []
+ f1r2:
+ - - meta:
+ type: map
+ description: A Groovy map containing sample information
+ - "${prefix}.f1r2.tar.gz":
+ type: file
+ description: file containing information to be passed to LearnReadOrientationModel
+ (only outputted when tumor_normal_pair mode is run)
+ pattern: "${prefix}.f1r2.tar.gz"
+ ontologies:
+ - edam: http://edamontology.org/format_3989 # GZIP format
+ versions_gatk4:
+ - - ${task.process}:
+ type: string
+ description: The name of the process
+ - gatk4:
+ type: string
+ description: The name of the tool
+ - gatk --version | sed -n '/GATK.*v/s/.*v//p':
+ type: eval
+ description: The expression to obtain the version of the tool
+topics:
+ versions:
+ - - ${task.process}:
+ type: string
+ description: The name of the process
+ - gatk4:
+ type: string
+ description: The name of the tool
+ - gatk --version | sed -n '/GATK.*v/s/.*v//p':
+ type: eval
+ description: The expression to obtain the version of the tool
+authors:
+ - "@GCJMackenzie"
+ - "@ramprasadn"
+maintainers:
+ - "@GCJMackenzie"
+ - "@ramprasadn"
diff --git a/modules/nf-core/gatk4/mutect2/tests/main.nf.test b/modules/nf-core/gatk4/mutect2/tests/main.nf.test
new file mode 100644
index 00000000..9e7b0fe7
--- /dev/null
+++ b/modules/nf-core/gatk4/mutect2/tests/main.nf.test
@@ -0,0 +1,542 @@
+nextflow_process {
+
+ name "Test Process GATK4_MUTECT2"
+ script "../main.nf"
+ process "GATK4_MUTECT2"
+
+ tag "modules"
+ tag "modules_nfcore"
+ tag "gatk4"
+ tag "gatk4/mutect2"
+ config "./nextflow.config"
+
+ test("human - bam - tumor_normal_pair") {
+ when {
+ params {
+ module_args = "--normal-sample normal"
+ }
+ process {
+ """
+ input[0] = [
+ [
+ id:'test',
+ normal_id:'normal',
+ tumor_id:'tumour'
+ ],
+ [
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam', checkIfExists: true)
+ ],
+ [
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true)
+ ],
+ []
+ ]
+ input[1] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [
+ [ id:'genome' ],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)],
+ []
+ ]
+ input[3] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ input[4] = []
+ input[5] = []
+ input[6] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz', checkIfExists: true)
+ input[7] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz.tbi', checkIfExists: true)
+ input[8] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz', checkIfExists: true)
+ input[9] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz.tbi', checkIfExists: true)
+ """
+ }
+ }
+
+ then {
+ assert process.success
+ assertAll(
+ { assert snapshot(
+ path(process.out.vcf.get(0).get(1)).vcf.variantsMD5,
+ process.out.tbi.collect { file(it[1]).getName() },
+ process.out.stats,
+ process.out.f1r2,
+ process.out.findAll { key, val -> key.startsWith("versions") }
+ ).match() }
+ )
+ }
+ }
+
+ test("human - bam - tumor_normal_pair_f1r2") {
+
+ when {
+ params {
+ module_args = "--normal-sample normal --f1r2-tar-gz test.f1r2.tar.gz"
+ }
+ process {
+ """
+ input[0] = [
+ [
+ id:'test',
+ normal_id:'normal',
+ tumor_id:'tumour'
+ ],
+ [
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam', checkIfExists: true)
+ ],
+ [
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true)
+ ],
+ []
+ ]
+ input[1] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [
+ [ id:'genome' ],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)],
+ []
+ ]
+ input[3] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ input[4] = []
+ input[5] = []
+ input[6] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz', checkIfExists: true)
+ input[7] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz.tbi', checkIfExists: true)
+ input[8] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz', checkIfExists: true)
+ input[9] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz.tbi', checkIfExists: true)
+ """
+ }
+ }
+ then {
+ assert process.success
+ assertAll(
+ { assert snapshot(
+ path(process.out.vcf.get(0).get(1)).vcf.variantsMD5,
+ process.out.tbi.collect { file(it[1]).getName() },
+ process.out.stats,
+ process.out.f1r2.collect { file(it[1]).getName() },
+ process.out.findAll { key, val -> key.startsWith("versions") }
+ ).match() }
+ )
+ }
+ }
+
+ test("human - bam - tumor_only"){
+ when {
+ params {
+ module_args = ''
+ }
+ process {
+ """
+ input[0] = [
+ [ id:'test'],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam', checkIfExists: true)],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true)],
+ []
+ ]
+ input[1] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [
+ [ id:'genome' ],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)],
+ []
+ ]
+ input[3] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ input[4] = []
+ input[5] = []
+ input[6] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz', checkIfExists: true)
+ input[7] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz.tbi', checkIfExists: true)
+ input[8] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz', checkIfExists: true)
+ input[9] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz.tbi', checkIfExists: true)
+ """
+ }
+ }
+ then {
+ assert process.success
+ assertAll(
+ { assert snapshot(
+ path(process.out.vcf.get(0).get(1)).vcf.variantsMD5,
+ process.out.tbi.collect { file(it[1]).getName() },
+ process.out.stats,
+ process.out.f1r2,
+ process.out.findAll { key, val -> key.startsWith("versions") }
+ ).match() }
+ )
+ }
+ }
+
+ test("human - cram"){
+ when {
+ params {
+ module_args = ''
+ }
+ process{
+ """
+ input[0] = [
+ [ id:'test'],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test2.paired_end.recalibrated.sorted.cram', checkIfExists: true)],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test2.paired_end.recalibrated.sorted.cram.crai', checkIfExists: true)],
+ []
+ ]
+ input[1] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [
+ [ id:'genome' ],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)],
+ []
+ ]
+ input[3] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ input[4] = []
+ input[5] = []
+ input[6] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz', checkIfExists: true)
+ input[7] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz.tbi', checkIfExists: true)
+ input[8] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz', checkIfExists: true)
+ input[9] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz.tbi', checkIfExists: true)
+ """
+ }
+ }
+ then {
+ assert process.success
+ assertAll(
+ { assert snapshot(
+ path(process.out.vcf.get(0).get(1)).vcf.variantsMD5,
+ process.out.tbi.collect { file(it[1]).getName() },
+ process.out.stats,
+ process.out.f1r2,
+ process.out.findAll { key, val -> key.startsWith("versions") }
+ ).match() }
+ )
+ }
+ }
+
+ test("human - bam - generate_pon") {
+ when {
+ params {
+ module_args = ''
+ }
+ process {
+ """
+ input[0] = [
+ [ id:'test'],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam', checkIfExists: true)],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true)],
+ []
+ ]
+ input[1] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [
+ [ id:'genome' ],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)],
+ []
+ ]
+ input[3] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ input[4] = []
+ input[5] = []
+ input[6] = []
+ input[7] = []
+ input[8] = []
+ input[9] = []
+ """
+ }
+ }
+ then {
+ assert process.success
+ assertAll(
+ { assert snapshot(
+ path(process.out.vcf.get(0).get(1)).vcf.variantsMD5,
+ process.out.tbi.collect { file(it[1]).getName() },
+ process.out.stats,
+ process.out.f1r2,
+ process.out.findAll { key, val -> key.startsWith("versions") }
+ ).match() }
+ )
+ }
+ }
+
+ test("mitochondria - bam"){
+ when {
+ params {
+ module_args = "--mitochondria-mode"
+ }
+ process {
+ """
+ input[0] = [
+ [ id:'test'],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/mitochon_standin.recalibrated.sorted.bam', checkIfExists: true)],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/mitochon_standin.recalibrated.sorted.bam.bai', checkIfExists: true)],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.bed', checkIfExists: true)]
+ ]
+ input[1] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [
+ [ id:'genome' ],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true)],
+ []
+ ]
+ input[3] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.dict', checkIfExists: true)
+ ]
+ input[4] = []
+ input[5] = []
+ input[6] = []
+ input[7] = []
+ input[8] = []
+ input[9] = []
+ """
+ }
+ }
+ then {
+ assert process.success
+ assertAll(
+ { assert snapshot(
+ path(process.out.vcf.get(0).get(1)).vcf.variantsMD5,
+ process.out.tbi.collect { file(it[1]).getName() },
+ process.out.stats,
+ process.out.f1r2,
+ process.out.findAll { key, val -> key.startsWith("versions") }
+ ).match() }
+ )
+ }
+ }
+
+ test("mitochondria - bam - gz_ref"){
+ when {
+ params {
+ module_args = "--mitochondria-mode"
+ }
+ process {
+ """
+ input[0] = [
+ [ id:'test'],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/mitochon_standin.recalibrated.sorted.bam', checkIfExists: true)],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/mitochon_standin.recalibrated.sorted.bam.bai', checkIfExists: true)],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.bed', checkIfExists: true)]
+ ]
+ input[1] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.gz', checkIfExists: true)
+ ]
+ input[2] = [
+ [ id:'genome' ],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.gz.fai', checkIfExists: true)],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.gz.gzi', checkIfExists: true)]
+ ]
+ input[3] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.dict', checkIfExists: true)
+ ]
+ input[4] = []
+ input[5] = []
+ input[6] = []
+ input[7] = []
+ input[8] = []
+ input[9] = []
+ """
+ }
+ }
+ then {
+ assert process.success
+ assertAll(
+ { assert snapshot(
+ path(process.out.vcf.get(0).get(1)).vcf.variantsMD5,
+ process.out.tbi.collect { file(it[1]).getName() },
+ process.out.stats,
+ process.out.f1r2,
+ process.out.findAll { key, val -> key.startsWith("versions") }
+ ).match() }
+ )
+ }
+ }
+
+ test("human - bam - tumor_normal_pair_f1r2 - stub"){
+
+ options "-stub"
+
+ when {
+ params {
+ module_args = ''
+ }
+ process {
+ """
+ input[0] = [
+ [
+ id:'test',
+ normal_id:'normal',
+ tumor_id:'tumour'
+ ],
+ [
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam', checkIfExists: true)
+ ],
+ [
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true)
+ ],
+ []
+ ]
+ input[1] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [
+ [ id:'genome' ],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)],
+ []
+ ]
+ input[3] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ input[4] = []
+ input[5] = []
+ input[6] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz', checkIfExists: true)
+ input[7] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz.tbi', checkIfExists: true)
+ input[8] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz', checkIfExists: true)
+ input[9] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz.tbi', checkIfExists: true)
+ """
+ }
+ }
+ then {
+ assert process.success
+ assertAll(
+ { assert snapshot(sanitizeOutput(process.out)).match() }
+ )
+ }
+ }
+
+ test("human - bam - tumor_normal_pair - force_call") {
+ when {
+ params {
+ module_args = ""
+ }
+ process {
+ """
+ input[0] = [
+ [
+ id:'test',
+ normal_id:'normal',
+ tumor_id:'tumour'
+ ],
+ [
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam', checkIfExists: true)
+ ],
+ [
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true),
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true)
+ ],
+ []
+ ]
+ input[1] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [
+ [ id:'genome' ],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)],
+ []
+ ]
+ input[3] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ input[4] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/axiom_exome_plus.genotypes.all_populations.poly.hg38.vcf.gz', checkIfExists: true)
+ input[5] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/axiom_exome_plus.genotypes.all_populations.poly.hg38.vcf.gz.tbi', checkIfExists: true)
+ input[6] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz', checkIfExists: true)
+ input[7] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz.tbi', checkIfExists: true)
+ input[8] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz', checkIfExists: true)
+ input[9] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz.tbi', checkIfExists: true)
+ """
+ }
+ }
+
+ then {
+ assert process.success
+ assertAll(
+ { assert snapshot(
+ path(process.out.vcf.get(0).get(1)).vcf.variantsMD5,
+ process.out.tbi.collect { file(it[1]).getName() },
+ process.out.stats,
+ process.out.f1r2,
+ process.out.findAll { key, val -> key.startsWith("versions") }
+ ).match() }
+ )
+ }
+ }
+
+ test("human - bam - tumor_only - force_call"){
+ when {
+ params {
+ module_args = ''
+ }
+ process {
+ """
+ input[0] = [
+ [ id:'test'],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam', checkIfExists: true)],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true)],
+ []
+ ]
+ input[1] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true)
+ ]
+ input[2] = [
+ [ id:'genome' ],
+ [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true)],
+ []
+ ]
+ input[3] = [
+ [ id:'genome' ],
+ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.dict', checkIfExists: true)
+ ]
+ input[4] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/axiom_exome_plus.genotypes.all_populations.poly.hg38.vcf.gz', checkIfExists: true)
+ input[5] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/axiom_exome_plus.genotypes.all_populations.poly.hg38.vcf.gz.tbi', checkIfExists: true)
+ input[6] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz', checkIfExists: true)
+ input[7] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/gnomAD.r2.1.1.vcf.gz.tbi', checkIfExists: true)
+ input[8] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz', checkIfExists: true)
+ input[9] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/germlineresources/mills_and_1000G.indels.hg38.vcf.gz.tbi', checkIfExists: true)
+ """
+ }
+ }
+ then {
+ assert process.success
+ assertAll(
+ { assert snapshot(
+ path(process.out.vcf.get(0).get(1)).vcf.variantsMD5,
+ process.out.tbi.collect { file(it[1]).getName() },
+ process.out.stats,
+ process.out.f1r2,
+ process.out.findAll { key, val -> key.startsWith("versions") }
+ ).match() }
+ )
+ }
+ }
+}
diff --git a/modules/nf-core/gatk4/mutect2/tests/main.nf.test.snap b/modules/nf-core/gatk4/mutect2/tests/main.nf.test.snap
new file mode 100644
index 00000000..5f8c7fc8
--- /dev/null
+++ b/modules/nf-core/gatk4/mutect2/tests/main.nf.test.snap
@@ -0,0 +1,363 @@
+{
+ "human - bam - generate_pon": {
+ "content": [
+ "876aa6be01c0c8fc71ad8e99ed842240",
+ [
+ "test.vcf.gz.tbi"
+ ],
+ [
+ [
+ {
+ "id": "test"
+ },
+ "test.vcf.gz.stats:md5,b569ce66bbffe9588b3d221e821023ee"
+ ]
+ ],
+ [
+
+ ],
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_MUTECT2",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T13:04:08.972426",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "human - bam - tumor_only - force_call": {
+ "content": [
+ "9c2928d0e751262c048ac162b9223e4e",
+ [
+ "test.vcf.gz.tbi"
+ ],
+ [
+ [
+ {
+ "id": "test"
+ },
+ "test.vcf.gz.stats:md5,2398263886ecb546c8055af4fbad6040"
+ ]
+ ],
+ [
+
+ ],
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_MUTECT2",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T13:19:05.012814",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "human - bam - tumor_normal_pair": {
+ "content": [
+ "7418ed45a029394253817a5eb7149334",
+ [
+ "test.vcf.gz.tbi"
+ ],
+ [
+ [
+ {
+ "id": "test",
+ "normal_id": "normal",
+ "tumor_id": "tumour"
+ },
+ "test.vcf.gz.stats:md5,17d2091015d04cbd4a26b7a67dc659e6"
+ ]
+ ],
+ [
+
+ ],
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_MUTECT2",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T12:42:02.158155",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "human - cram": {
+ "content": [
+ "1b65f1a163b517944bf2e4b74230e035",
+ [
+ "test.vcf.gz.tbi"
+ ],
+ [
+ [
+ {
+ "id": "test"
+ },
+ "test.vcf.gz.stats:md5,55ed641e16089afb33cdbc478e202d3d"
+ ]
+ ],
+ [
+
+ ],
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_MUTECT2",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T12:59:18.462801",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "mitochondria - bam": {
+ "content": [
+ "ea70f79e33805a2c0b47b32a48a8d26f",
+ [
+ "test.vcf.gz.tbi"
+ ],
+ [
+ [
+ {
+ "id": "test"
+ },
+ "test.vcf.gz.stats:md5,fc6ea14ca2da346babe78161beea28c9"
+ ]
+ ],
+ [
+
+ ],
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_MUTECT2",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T13:04:37.912171",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "human - bam - tumor_only": {
+ "content": [
+ "1b65f1a163b517944bf2e4b74230e035",
+ [
+ "test.vcf.gz.tbi"
+ ],
+ [
+ [
+ {
+ "id": "test"
+ },
+ "test.vcf.gz.stats:md5,55ed641e16089afb33cdbc478e202d3d"
+ ]
+ ],
+ [
+
+ ],
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_MUTECT2",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T12:54:23.03524",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "mitochondria - bam - gz_ref": {
+ "content": [
+ "ea70f79e33805a2c0b47b32a48a8d26f",
+ [
+ "test.vcf.gz.tbi"
+ ],
+ [
+ [
+ {
+ "id": "test"
+ },
+ "test.vcf.gz.stats:md5,fc6ea14ca2da346babe78161beea28c9"
+ ]
+ ],
+ [
+
+ ],
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_MUTECT2",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T13:05:04.049877",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "human - bam - tumor_normal_pair - force_call": {
+ "content": [
+ "63c4ff01a8316f4243b6b12b06ded74e",
+ [
+ "test.vcf.gz.tbi"
+ ],
+ [
+ [
+ {
+ "id": "test",
+ "normal_id": "normal",
+ "tumor_id": "tumour"
+ },
+ "test.vcf.gz.stats:md5,81390058f99b80db30c89020aa9fc546"
+ ]
+ ],
+ [
+
+ ],
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_MUTECT2",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T13:13:17.23664",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "human - bam - tumor_normal_pair_f1r2 - stub": {
+ "content": [
+ {
+ "f1r2": [
+ [
+ {
+ "id": "test",
+ "normal_id": "normal",
+ "tumor_id": "tumour"
+ },
+ "test.f1r2.tar.gz:md5,68b329da9893e34099c7d8ad5cb9c940"
+ ]
+ ],
+ "stats": [
+ [
+ {
+ "id": "test",
+ "normal_id": "normal",
+ "tumor_id": "tumour"
+ },
+ "test.vcf.gz.stats:md5,d41d8cd98f00b204e9800998ecf8427e"
+ ]
+ ],
+ "tbi": [
+ [
+ {
+ "id": "test",
+ "normal_id": "normal",
+ "tumor_id": "tumour"
+ },
+ "test.vcf.gz.tbi:md5,d41d8cd98f00b204e9800998ecf8427e"
+ ]
+ ],
+ "vcf": [
+ [
+ {
+ "id": "test",
+ "normal_id": "normal",
+ "tumor_id": "tumour"
+ },
+ "test.vcf.gz:md5,68b329da9893e34099c7d8ad5cb9c940"
+ ]
+ ],
+ "versions_gatk4": [
+ [
+ "GATK4_MUTECT2",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T13:05:54.271544",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ },
+ "human - bam - tumor_normal_pair_f1r2": {
+ "content": [
+ "7418ed45a029394253817a5eb7149334",
+ [
+ "test.vcf.gz.tbi"
+ ],
+ [
+ [
+ {
+ "id": "test",
+ "normal_id": "normal",
+ "tumor_id": "tumour"
+ },
+ "test.vcf.gz.stats:md5,17d2091015d04cbd4a26b7a67dc659e6"
+ ]
+ ],
+ [
+ "test.f1r2.tar.gz"
+ ],
+ {
+ "versions_gatk4": [
+ [
+ "GATK4_MUTECT2",
+ "gatk4",
+ "4.7.0.0"
+ ]
+ ]
+ }
+ ],
+ "timestamp": "2026-08-18T12:48:06.591264",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.6"
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/nf-core/gatk4/mutect2/tests/nextflow.config b/modules/nf-core/gatk4/mutect2/tests/nextflow.config
new file mode 100644
index 00000000..08e94285
--- /dev/null
+++ b/modules/nf-core/gatk4/mutect2/tests/nextflow.config
@@ -0,0 +1,5 @@
+process {
+ withName: GATK4_MUTECT2 {
+ ext.args = params.module_args
+ }
+}
diff --git a/nextflow.config b/nextflow.config
index ef1079a5..7cb2c502 100644
--- a/nextflow.config
+++ b/nextflow.config
@@ -223,7 +223,7 @@ manifest {
mainScript = 'main.nf'
defaultBranch = 'main'
nextflowVersion = '!>=26.04.0'
- version = '1.13.6'
+ version = '1.14.0dev'
doi = ''
}
diff --git a/nextflow_schema.json b/nextflow_schema.json
index 47936957..7048158d 100644
--- a/nextflow_schema.json
+++ b/nextflow_schema.json
@@ -140,6 +140,20 @@
"exists": true,
"pattern": "^\\S+\\.list$",
"description": "Path to the MSI baseline VCF file."
+ },
+ "panel_of_normals": {
+ "type": "string",
+ "format": "file-path",
+ "exists": true,
+ "pattern": "^\\S+\\.vcf\\.gz$",
+ "description": "Path to the panel of normals VCF file. Only used when `mutect2` is one of the specified callers."
+ },
+ "panel_of_normals_tbi": {
+ "type": "string",
+ "format": "file-path",
+ "exists": true,
+ "pattern": "^\\S+\\.vcf\\.gz\\.tbi$",
+ "description": "Path to the index of the panel of normals VCF file. Only used when `mutect2` is one of the specified callers."
}
},
"required": ["fasta"]
@@ -242,8 +256,9 @@
},
"callers": {
"type": "string",
- "description": "A comma delimited string of the available callers. Current options are: `haplotypecaller` and `vardict`.",
- "default": "haplotypecaller"
+ "description": "A comma delimited string of the available callers. Current options are: `haplotypecaller`, `vardict`, `elprep` and `mutect2`.",
+ "default": "haplotypecaller",
+ "pattern": "^((haplotypecaller|vardict|elprep|mutect2)?,?)*(?=26.04.0"
},
{
- "@id": "#84577f03-f447-4b0b-b2fb-5422aec4656d",
+ "@id": "#c826b3b7-b8ef-4fcd-8257-778b050fcc73",
"@type": "TestSuite",
"instance": [
{
- "@id": "#43065218-569c-4a08-b9a4-bca918d8c09a"
+ "@id": "#bd82b942-d87b-49da-91b1-afd3de258b7b"
}
],
"mainEntity": {
@@ -192,7 +192,7 @@
"name": "Test suite for nf-cmgg/smallvariants"
},
{
- "@id": "#43065218-569c-4a08-b9a4-bca918d8c09a",
+ "@id": "#bd82b942-d87b-49da-91b1-afd3de258b7b",
"@type": "TestInstance",
"name": "GitHub Actions workflow for testing nf-cmgg/smallvariants",
"resource": "repos/nf-cmgg/smallvariants/actions/workflows/nf-test.yml",
diff --git a/subworkflows/local/cram_call_gatk4/main.nf b/subworkflows/local/cram_call_haplotypecaller/main.nf
similarity index 97%
rename from subworkflows/local/cram_call_gatk4/main.nf
rename to subworkflows/local/cram_call_haplotypecaller/main.nf
index 274c27d0..654ad3cc 100644
--- a/subworkflows/local/cram_call_gatk4/main.nf
+++ b/subworkflows/local/cram_call_haplotypecaller/main.nf
@@ -1,5 +1,5 @@
//
-// Call the variants using GATK4 tooling
+// Call the variants using HaplotypeCaller
//
include { GATK4_CALIBRATEDRAGSTRMODEL } from '../../../modules/nf-core/gatk4/calibratedragstrmodel/main'
@@ -8,7 +8,7 @@ include { BCFTOOLS_STATS } from '../../../modules/nf-
include { VCF_CONCAT_BCFTOOLS } from '../vcf_concat_bcftools/main'
-workflow CRAM_CALL_GATK4 {
+workflow CRAM_CALL_HAPLOTYPECALLER {
take:
ch_input // channel: [mandatory] [ val(meta), path(cram), path(crai), path(bed) ] => sample CRAM files and their indexes with the split bed files
ch_fasta // channel: [mandatory] [ val(meta), path(fasta) ] => fasta reference
diff --git a/subworkflows/local/cram_call_gatk4/tests/main.nf.test b/subworkflows/local/cram_call_haplotypecaller/tests/main.nf.test
similarity index 95%
rename from subworkflows/local/cram_call_gatk4/tests/main.nf.test
rename to subworkflows/local/cram_call_haplotypecaller/tests/main.nf.test
index 1807948a..8ebe782b 100644
--- a/subworkflows/local/cram_call_gatk4/tests/main.nf.test
+++ b/subworkflows/local/cram_call_haplotypecaller/tests/main.nf.test
@@ -1,15 +1,15 @@
nextflow_workflow {
- name "Test Workflow CRAM_CALL_GATK4"
+ name "Test Workflow CRAM_CALL_HAPLOTYPECALLER"
script "../main.nf"
- workflow "CRAM_CALL_GATK4"
+ workflow "CRAM_CALL_HAPLOTYPECALLER"
tag "subworkflows"
tag "subworkflows_local"
- tag "cram_call_gatk4"
+ tag "CRAM_CALL_HAPLOTYPECALLER"
tag "vcf_concat_bcftools"
- test("cram_call_gatk4 - default") {
+ test("CRAM_CALL_HAPLOTYPECALLER - default") {
when {
@@ -66,7 +66,7 @@ nextflow_workflow {
}
- test("cram_call_gatk4 - dragstr") {
+ test("CRAM_CALL_HAPLOTYPECALLER - dragstr") {
when {
diff --git a/subworkflows/local/cram_call_gatk4/tests/main.nf.test.snap b/subworkflows/local/cram_call_haplotypecaller/tests/main.nf.test.snap
similarity index 96%
rename from subworkflows/local/cram_call_gatk4/tests/main.nf.test.snap
rename to subworkflows/local/cram_call_haplotypecaller/tests/main.nf.test.snap
index 908fb0d9..11d4837a 100644
--- a/subworkflows/local/cram_call_gatk4/tests/main.nf.test.snap
+++ b/subworkflows/local/cram_call_haplotypecaller/tests/main.nf.test.snap
@@ -1,5 +1,5 @@
{
- "cram_call_gatk4 - default": {
+ "CRAM_CALL_HAPLOTYPECALLER - default": {
"content": [
[
[
@@ -41,7 +41,7 @@
"nextflow": "26.04.1"
}
},
- "cram_call_gatk4 - dragstr": {
+ "CRAM_CALL_HAPLOTYPECALLER - dragstr": {
"content": [
[
[
diff --git a/subworkflows/local/cram_call_mutect2/main.nf b/subworkflows/local/cram_call_mutect2/main.nf
new file mode 100644
index 00000000..de71d7bd
--- /dev/null
+++ b/subworkflows/local/cram_call_mutect2/main.nf
@@ -0,0 +1,72 @@
+//
+// Call the variants using HaplotypeCaller
+//
+
+include { GATK4_MUTECT2 } from '../../../modules/nf-core/gatk4/mutect2/main'
+include { GATK4_FILTERMUTECTCALLS } from '../../../modules/nf-core/gatk4/filtermutectcalls/main'
+include { BCFTOOLS_STATS } from '../../../modules/nf-core/bcftools/stats/main'
+
+include { VCF_CONCAT_BCFTOOLS } from '../vcf_concat_bcftools/main'
+
+workflow CRAM_CALL_MUTECT2 {
+ take:
+ ch_input // channel: [mandatory] [ val(meta), path(cram), path(crai), path(bed) ] => sample CRAM files and their indexes with the split bed files
+ ch_fasta // channel: [mandatory] [ val(meta), path(fasta) ] => fasta reference
+ ch_fai // channel: [mandatory] [ val(meta), path(fai) ] => fasta reference index
+ ch_dict // channel: [mandatory] [ val(meta), path(dict) ] => sequence dictionary
+ ch_dbsnp // channel: [optional] [ path(dbsnp) ] => The VCF containing the dbsnp variants
+ ch_dbsnp_tbi // channel: [optional] [ path(dbsnp_tbi) ] => The index of the dbsnp VCF
+ ch_panel_of_normals // channel: [optional] [ path(panel_of_normals) ] => The VCF containing the panel of normals variants
+ ch_panel_of_normals_tbi // channel: [optional] [ path(panel_of_normals_tbi) ] => The index of the panel of normals VCF
+
+ main:
+
+ GATK4_MUTECT2(
+ ch_input.map { meta, cram, crai, bed ->
+ def new_meta = meta + [caller:'mutect2', family_samples: meta.sample]
+ tuple(new_meta, cram, crai, bed)
+ },
+ ch_fasta,
+ ch_fai.map { meta, fai -> tuple(meta, fai, [])},
+ ch_dict,
+ [],
+ [],
+ ch_dbsnp == [[],[]] ? [] : ch_dbsnp.map { _meta, dbsnp -> dbsnp },
+ ch_dbsnp_tbi == [[],[]] ? [] : ch_dbsnp_tbi.map { _meta, dbsnp_tbi -> dbsnp_tbi },
+ ch_panel_of_normals,
+ ch_panel_of_normals_tbi
+ )
+
+ // TODO handle stats
+ def ch_mutect_calls = GATK4_MUTECT2.out.vcf
+ .join(GATK4_MUTECT2.out.tbi, failOnDuplicate: true, failOnMismatch: true)
+ .join(GATK4_MUTECT2.out.stats, failOnDuplicate: true, failOnMismatch: true)
+ .map { meta, vcf, tbi, stats -> tuple(meta, vcf, tbi, stats, [], [], [], []) }
+
+ GATK4_FILTERMUTECTCALLS(
+ ch_mutect_calls,
+ ch_fasta,
+ ch_fai,
+ ch_dict
+ )
+
+ def ch_calls = GATK4_FILTERMUTECTCALLS.out.vcf
+ .join(GATK4_FILTERMUTECTCALLS.out.tbi, failOnDuplicate: true, failOnMismatch: true)
+
+ VCF_CONCAT_BCFTOOLS(
+ ch_calls
+ )
+
+ BCFTOOLS_STATS(
+ VCF_CONCAT_BCFTOOLS.out.vcfs,
+ [[],[]],
+ [[],[]],
+ [[],[]],
+ [[],[]],
+ [[],[]]
+ )
+
+ emit:
+ vcfs = VCF_CONCAT_BCFTOOLS.out.vcfs // channel: [ val(meta), path(vcf), path(tbi) ]
+ reports = BCFTOOLS_STATS.out.stats // channel: [ val(meta), path(stats) ]
+}
diff --git a/subworkflows/local/cram_call_mutect2/tests/main.nf.test b/subworkflows/local/cram_call_mutect2/tests/main.nf.test
new file mode 100644
index 00000000..b0efc0e3
--- /dev/null
+++ b/subworkflows/local/cram_call_mutect2/tests/main.nf.test
@@ -0,0 +1,68 @@
+nextflow_workflow {
+
+ name "Test Workflow CRAM_CALL_MUTECT2"
+ script "../main.nf"
+ workflow "CRAM_CALL_MUTECT2"
+
+ tag "subworkflows"
+ tag "subworkflows_local"
+ tag "CRAM_CALL_MUTECT2"
+ tag "vcf_concat_bcftools"
+
+ test("CRAM_CALL_MUTECT2 - default") {
+
+
+ when {
+ params {
+ callers = "mutect2"
+ }
+ workflow {
+ """
+ input[0] = channel.of([
+ [id:"NA24143.00001", sample:"NA24143", family:"Ashkenazim", family_samples:"NA24143", split_count:3],
+ file(params.cram1, checkIfExists:true),
+ file(params.crai1, checkIfExists:true),
+ file(params.split1, checkIfExists:true)
+ ],[
+ [id:"NA24143.00002", sample:"NA24143", family:"Ashkenazim", family_samples:"NA24143", split_count:3],
+ file(params.cram1, checkIfExists:true),
+ file(params.crai1, checkIfExists:true),
+ file(params.split2, checkIfExists:true)
+ ],[
+ [id:"NA24143.00003", sample:"NA24143", family:"Ashkenazim", family_samples:"NA24143", split_count:3],
+ file(params.cram1, checkIfExists:true),
+ file(params.crai1, checkIfExists:true),
+ file(params.split3, checkIfExists:true)
+ ])
+ input[1] = channel.value([
+ [id:"fasta"],
+ file(params.fasta, checkIfExists:true)
+ ])
+ input[2] = channel.value([
+ [id:"fai"],
+ file(params.fai, checkIfExists:true)
+ ])
+ input[3] = channel.value([
+ [id:"dict"],
+ file(params.dict, checkIfExists:true)
+ ])
+ input[4] = []
+ input[5] = []
+ input[6] = []
+ input[7] = []
+ """
+ }
+ }
+
+ then {
+ assertAll(
+ { assert workflow.success },
+ { assert snapshot(
+ workflow.out.vcfs.collect { [it[0], "${file(it[1]).name},variantsMD5:${path(it[1]).vcf.variantsMD5}", file(it[2]).name] },
+ workflow.out.reports
+ ).match() }
+ )
+ }
+
+ }
+}
diff --git a/subworkflows/local/cram_call_mutect2/tests/main.nf.test.snap b/subworkflows/local/cram_call_mutect2/tests/main.nf.test.snap
new file mode 100644
index 00000000..0bd0a655
--- /dev/null
+++ b/subworkflows/local/cram_call_mutect2/tests/main.nf.test.snap
@@ -0,0 +1,44 @@
+{
+ "CRAM_CALL_MUTECT2 - default": {
+ "content": [
+ [
+ [
+ {
+ "groupSize": 3,
+ "groupTarget": {
+ "id": "NA24143",
+ "sample": "NA24143",
+ "family": "Ashkenazim",
+ "family_samples": "NA24143",
+ "split_count": 3,
+ "caller": "mutect2"
+ }
+ },
+ "NA24143.concat.vcf.gz,variantsMD5:53d915ee4a2d5e44402c7d223699f792",
+ "NA24143.concat.vcf.gz.tbi"
+ ]
+ ],
+ [
+ [
+ {
+ "groupSize": 3,
+ "groupTarget": {
+ "id": "NA24143",
+ "sample": "NA24143",
+ "family": "Ashkenazim",
+ "family_samples": "NA24143",
+ "split_count": 3,
+ "caller": "mutect2"
+ }
+ },
+ "NA24143.bcftools_stats.txt:md5,062d7725d095dbdbf7fefbe6ea8079dc"
+ ]
+ ]
+ ],
+ "timestamp": "2026-09-07T15:18:23.905783673",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.3"
+ }
+ }
+}
\ No newline at end of file
diff --git a/subworkflows/local/vcf_roh_automap/main.nf b/subworkflows/local/vcf_roh_automap/main.nf
index aa184acf..cb89532a 100644
--- a/subworkflows/local/vcf_roh_automap/main.nf
+++ b/subworkflows/local/vcf_roh_automap/main.nf
@@ -30,8 +30,29 @@ workflow VCF_ROH_AUTOMAP {
ch_valid_repeats = ch_repeats
}
+ def ch_automap_input = ch_vcfs.filter { meta, vcf, _tbi ->
+ // Check the amount of variants for all VCFs that are under 1 MB (automap requires at least 10000 variants to run)
+ if(vcf?.size() < 1000000) {
+ def var_count = 0
+ vcf.withInputStream { stream ->
+ new java.util.zip.GZIPInputStream(stream).withReader('UTF-8') { reader ->
+ reader.eachLine { line ->
+ if(!line.startsWith("#")) {
+ var_count += 1
+ }
+ }
+ }
+ }
+ if(var_count < 10000) {
+ log.warn("VCF file '${vcf}' for sample '${meta.id}' only has ${var_count} variants. Automap requires at least 10000 variants to run. Skipping this VCF.")
+ return false
+ }
+ }
+ return true
+ }
+
AUTOMAP_AUTOMAP(
- ch_vcfs,
+ ch_automap_input,
ch_valid_repeats,
ch_panel,
hg_genome
diff --git a/tests/pipeline/callers/main.nf.test b/tests/pipeline/callers/main.nf.test
index de3ac974..5a129c49 100644
--- a/tests/pipeline/callers/main.nf.test
+++ b/tests/pipeline/callers/main.nf.test
@@ -37,6 +37,35 @@ nextflow_pipeline {
}
+ test("pipeline_callers - mutect2") {
+
+ when {
+ params {
+ outdir = "${outputDir}"
+ callers = "mutect2"
+ }
+ }
+
+ then {
+ assertAll(
+ { assert workflow.success },
+ { assert snapshot(
+ path("${outputDir}")
+ .list()
+ .collect { Utils.getRecursiveFileNames(it, "${outputDir}") }
+ .flatten()
+ .findAll {
+ !(it.contains("/execution_") || it.contains("/params_") || it.contains("/pipeline_") || it.contains("DONE"))
+ }
+ .collect {
+ it.replace(Utils.getDynamicOutputName(), "_")
+ }
+ ).match() }
+ )
+ }
+
+ }
+
test("pipeline_callers - haplotypecaller") {
when {
diff --git a/tests/pipeline/callers/main.nf.test.snap b/tests/pipeline/callers/main.nf.test.snap
index afd4979c..2b39f0c8 100644
--- a/tests/pipeline/callers/main.nf.test.snap
+++ b/tests/pipeline/callers/main.nf.test.snap
@@ -229,5 +229,27 @@
"nf-test": "0.9.5",
"nextflow": "25.10.4"
}
+ },
+ "pipeline_callers - mutect2": {
+ "content": [
+ [
+ "Ashkenazim/NA24149__/NA24149.bed",
+ "Ashkenazim/NA24149__/NA24149.per-base.bed.gz",
+ "Ashkenazim/NA24149__/NA24149.per-base.bed.gz.csi",
+ "Ashkenazim/NA24149__/mosdepth/NA24149.global.dist.txt",
+ "Ashkenazim/NA24149__/mosdepth/NA24149.region.dist.txt",
+ "Ashkenazim/NA24149__/mosdepth/NA24149.summary.txt",
+ "Ashkenazim/NA24149__/msi/NA24149_all_msi",
+ "Ashkenazim/NA24149__/msi/NA24149_dis_msi",
+ "Ashkenazim/NA24149__/msi/NA24149_summary_msi",
+ "Ashkenazim/NA24149__/msi/NA24149_unstable_msi",
+ "_/samplesheet.csv"
+ ]
+ ],
+ "timestamp": "2026-09-07T16:14:51.995560164",
+ "meta": {
+ "nf-test": "0.9.5",
+ "nextflow": "26.04.3"
+ }
}
}
\ No newline at end of file
diff --git a/workflows/smallvariants.nf b/workflows/smallvariants.nf
index 636d120c..e685170e 100644
--- a/workflows/smallvariants.nf
+++ b/workflows/smallvariants.nf
@@ -17,10 +17,11 @@ include { methodsDescriptionText } from '../subworkflows/local/utils_
include { CRAM_PREPARE_SAMTOOLS_BEDTOOLS } from '../subworkflows/local/cram_prepare_samtools_bedtools/main'
include { INPUT_SPLIT_BEDTOOLS } from '../subworkflows/local/input_split_bedtools/main'
-include { CRAM_CALL_GATK4 } from '../subworkflows/local/cram_call_gatk4/main'
+include { CRAM_CALL_HAPLOTYPECALLER } from '../subworkflows/local/cram_call_haplotypecaller/main'
include { GVCF_JOINT_GENOTYPE_GATK4 } from '../subworkflows/local/gvcf_joint_genotype_gatk4/main'
include { BAM_CALL_ELPREP } from '../subworkflows/local/bam_call_elprep/main'
include { BAM_CALL_VARDICTJAVA } from '../subworkflows/local/bam_call_vardictjava/main'
+include { CRAM_CALL_MUTECT2 } from '../subworkflows/local/cram_call_mutect2/main'
include { VCF_EXTRACT_RELATE_SOMALIER } from '../subworkflows/local/vcf_extract_relate_somalier/main'
include { VCF_PED_RTGTOOLS } from '../subworkflows/local/vcf_ped_rtgtools/main'
include { VCF_ANNOTATION } from '../subworkflows/local/vcf_annotation/main'
@@ -106,6 +107,8 @@ workflow SMALLVARIANTS {
elsites // path: path to the elsites file for elprep
msi_baseline // path: path to the msi_baseline file
updio_regions // path: path to the BED file with regions to be used by UPDio
+ panel_of_normals // path: path to the panel of normals VCF file
+ panel_of_normals_tbi // path: path to the index of the panel of normals VCF file
// Boolean inputs
dragstr // boolean: create a dragstr model and use it for haplotypecaller
@@ -148,36 +151,39 @@ workflow SMALLVARIANTS {
// Importing and convert the input files passed through the parameters to channels
//
- def ch_fasta_ready = channel.value([[id:"reference"], fasta])
- def ch_fai = fai ? channel.value([[id:"reference"], fai]) : null
- def ch_dict = dict ? channel.value([[id:"reference"], dict]) : null
- def ch_elfasta = elfasta ? channel.value([[id:"reference"], elfasta]) : null
- def ch_strtablefile = strtablefile ? channel.value([[id:"reference"], strtablefile]) : null
- def ch_sdf = sdf ? channel.value([[id:'reference'], sdf]) : null
+ def ch_fasta_ready = channel.value([[id:"reference"], fasta])
+ def ch_fai = fai ? channel.value([[id:"reference"], fai]) : null
+ def ch_dict = dict ? channel.value([[id:"reference"], dict]) : null
+ def ch_elfasta = elfasta ? channel.value([[id:"reference"], elfasta]) : null
+ def ch_strtablefile = strtablefile ? channel.value([[id:"reference"], strtablefile]) : null
+ def ch_sdf = sdf ? channel.value([[id:'reference'], sdf]) : null
- def ch_default_roi = roi ? channel.value(roi) : []
+ def ch_default_roi = roi ? channel.value(roi) : []
- def ch_dbsnp_ready = dbsnp ? channel.value([[id:"dbsnp"], dbsnp]) : [[],[]]
- def ch_dbsnp_tbi = dbsnp_tbi ? channel.value([[id:"dbsnp"], dbsnp_tbi]) : [[],[]]
+ def ch_dbsnp_ready = dbsnp ? channel.value([[id:"dbsnp"], dbsnp]) : [[],[]]
+ def ch_dbsnp_tbi = dbsnp_tbi ? channel.value([[id:"dbsnp"], dbsnp_tbi]) : [[],[]]
- def ch_somalier_sites = somalier_sites ? channel.value([[id:"somalier_sites"], somalier_sites]) : [[],[]]
+ def ch_somalier_sites = somalier_sites ? channel.value([[id:"somalier_sites"], somalier_sites]) : [[],[]]
- def ch_vep_cache = vep_cache ? channel.value([[id:'cache'], file(vep_cache)]) : []
+ def ch_vep_cache = vep_cache ? channel.value([[id:'cache'], file(vep_cache)]) : []
- def ch_vcfanno_config = vcfanno_config ? channel.value(vcfanno_config) : []
- def ch_vcfanno_lua = vcfanno_lua ? channel.value(vcfanno_lua) : []
- def ch_vcfanno_resources = vcfanno_resources ? channel.value(vcfanno_resources.split(";").collect{ res -> files(res, checkIfExists:true) }.flatten()) : []
+ def ch_vcfanno_config = vcfanno_config ? channel.value(vcfanno_config) : []
+ def ch_vcfanno_lua = vcfanno_lua ? channel.value(vcfanno_lua) : []
+ def ch_vcfanno_resources = vcfanno_resources ? channel.value(vcfanno_resources.split(";").collect{ res -> files(res, checkIfExists:true) }.flatten()) : []
- def ch_updio_common_cnvs = updio_common_cnvs ? channel.value([[id:'updio_cnv'], updio_common_cnvs]) : [[],[]]
+ def ch_updio_common_cnvs = updio_common_cnvs ? channel.value([[id:'updio_cnv'], updio_common_cnvs]) : [[],[]]
- def ch_automap_repeats = automap_repeats ? channel.value([[id:"repeats"], automap_repeats]) : []
- def ch_automap_panel = automap_panel ? channel.value([[id:"automap_panel"], automap_panel]) : [[],[]]
+ def ch_automap_repeats = automap_repeats ? channel.value([[id:"repeats"], automap_repeats]) : []
+ def ch_automap_panel = automap_panel ? channel.value([[id:"automap_panel"], automap_panel]) : [[],[]]
- def ch_elsites = elsites ? channel.fromPath(elsites).map{ elsites_file -> [[id:'elsites'], elsites_file] }.collect() : [[],[]]
+ def ch_elsites = elsites ? channel.fromPath(elsites).map{ elsites_file -> [[id:'elsites'], elsites_file] }.collect() : [[],[]]
- def ch_msi_baseline = msi_baseline ? channel.value([[id:"msi_baseline"], msi_baseline]) : [[],[]]
+ def ch_msi_baseline = msi_baseline ? channel.value([[id:"msi_baseline"], msi_baseline]) : [[],[]]
- def ch_updio_regions = updio_regions ? channel.value(updio_regions) : []
+ def ch_updio_regions = updio_regions ? channel.value(updio_regions) : []
+
+ def ch_panel_of_normals = panel_of_normals ? channel.value(panel_of_normals) : []
+ def ch_panel_of_normals_tbi = panel_of_normals_tbi ? channel.value(panel_of_normals_tbi) : []
//
// Check for the presence of EnsemblVEP plugins that use extra files
@@ -538,7 +544,7 @@ workflow SMALLVARIANTS {
// Call variants with GATK4 HaplotypeCaller
//
- CRAM_CALL_GATK4(
+ CRAM_CALL_HAPLOTYPECALLER(
ch_caller_inputs.cram.filter { meta, _cram, _crai, _bed ->
// Filter out the entries that already have a GVCF
meta.type == "cram"
@@ -551,9 +557,9 @@ workflow SMALLVARIANTS {
ch_dbsnp_tbi_ready,
dragstr
)
- ch_gvcfs_ready = ch_gvcfs_ready.mix(CRAM_CALL_GATK4.out.gvcfs)
- ch_reports = ch_reports.mix(CRAM_CALL_GATK4.out.reports.map { _meta, report -> report })
- ch_gvcf_reports = ch_gvcf_reports.mix(CRAM_CALL_GATK4.out.reports)
+ ch_gvcfs_ready = ch_gvcfs_ready.mix(CRAM_CALL_HAPLOTYPECALLER.out.gvcfs)
+ ch_reports = ch_reports.mix(CRAM_CALL_HAPLOTYPECALLER.out.reports.map { _meta, report -> report })
+ ch_gvcf_reports = ch_gvcf_reports.mix(CRAM_CALL_HAPLOTYPECALLER.out.reports)
}
if("elprep" in callers) {
@@ -591,6 +597,24 @@ workflow SMALLVARIANTS {
ch_calls = ch_calls.mix(BAM_CALL_VARDICTJAVA.out.vcfs)
}
+ if("mutect2" in callers) {
+ //
+ // Call variants with GATK4 Mutect2
+ //
+
+ CRAM_CALL_MUTECT2(
+ ch_caller_inputs.cram,
+ ch_fasta_ready,
+ ch_fai_ready,
+ ch_dict_ready,
+ ch_dbsnp_ready,
+ ch_dbsnp_tbi_ready,
+ ch_panel_of_normals,
+ ch_panel_of_normals_tbi
+ )
+ ch_calls = ch_calls.mix(CRAM_CALL_MUTECT2.out.vcfs)
+ }
+
// Stop pipeline execution when only calls should happen
def ch_gvcfs_final = ch_gvcfs_ready.filter { !only_call }