diff --git a/CHANGELOG.md b/CHANGELOG.md
index 126f1ed9aa60503f8793f43f60ae2f2b233b9cb2..6c0db94722449604660b6d39e98957fd6380da93 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,43 @@ that users understand how the changes affect the new version.
 -->
 version 5.1.0-dev
 ---------------------------
++ Added a task for SnpEff.
++ Adjusted runtime settings for sambamba Markdup.
++ Added a task for sambamba Flagstat.
++ Added a task for Picard CollectWgsMetrics.
++ Added a task for Peach.
++ Added tasks for HMFtools:
+  + Amber
+  + Cobalt
+  + Cuppa
+  + CuppaChart
+  + GripssApplicationKt
+  + GripssHardFilterApplicationKt
+  + HealthChecker
+  + Linx
+  + Protect
+  + Purple
+  + Sage
+  + VirusInterpreter
++ Added a task for VirusBreakend.
++ Added a task for GridssAnnotateVcfRepeatmasker. 
++ Bumped GRIDSS version to 2.12.2.
++ Adjusted GRIDSS runtime settings.
++ Added optional inputs to GRIDSS:
+  + blacklistBed
+  + gridssProperties
++ Added a task for GRIDSS AnnotateInsertedSequence.
++ Added a task for ExtractSigPredictHRD.
++ Added a task for DeconstructSigs.
++ Added option useSoftclippingForSupplementary (default false) to
+  BWA mem.
++ Adjusted BWA mem runtime settings.
++ Added a task for bedtools coverage.
++ Added a task for bcftools filter.
++ Adjusted runtime settings for bcftools annotate.
++ Added optional inputs to bcftools annotate:
+  + inputFileIndex
+  + annsFileIndex
 + Update parameter_meta for macs2
 + Add sample position in array task.
 
diff --git a/bcftools.wdl b/bcftools.wdl
index 02a02563f622766f2481ecfd27c6668c6f0b27d1..88d97cd09465fee1384edc6b498504bbd2adf917 100644
--- a/bcftools.wdl
+++ b/bcftools.wdl
@@ -30,9 +30,11 @@ task Annotate {
         Boolean singleOverlaps = false
         Array[String] removeAnns = []
         File inputFile
+        File? inputFileIndex
         String outputPath = "output.vcf.gz"
 
         File? annsFile
+        File? annsFileIndex
         String? collapse
         String? exclude
         File? headerLines
@@ -45,8 +47,8 @@ task Annotate {
         File? samplesFile
 
         Int threads = 0
-        String memory = "256M"
-        Int timeMinutes = 1 + ceil(size(inputFile, "G"))
+        String memory = "4G"
+        Int timeMinutes = 60 + ceil(size(inputFile, "G"))
         String dockerImage = "quay.io/biocontainers/bcftools:1.10.2--h4f4756c_2"
     }
 
@@ -102,8 +104,10 @@ task Annotate {
         singleOverlaps: {description: "keep memory requirements low with very large annotation files.", category: "advanced"}
         removeAnns: {description: "List of annotations to remove (see man page for details).", category: "advanced"}
         inputFile: {description: "A vcf or bcf file.", category: "required"}
+        inputFileIndex: {description: "The index for the input vcf or bcf.", category: "common"}
         outputPath: {description: "The location the output VCF file should be written.", category: "common"}
-        annsFile: {description: "Bgzip-compressed and tabix-indexed file with annotations (see man page for details).", category: "advanced"}
+        annsFile: {description: "Bgzip-compressed and tabix-indexed file with annotations (see man page for details).", category: "common"}
+        annsFileIndex: {description: "The index for annsFile.", category: "common"}
         collapse: {description: "Treat as identical records with <snps|indels|both|all|some|none>, see man page for details.", category: "advanced"}
         exclude: {description: "Exclude sites for which the expression is true (see man page for details).", category: "advanced"}
         headerLines: {description: "Lines to append to the VCF header (see man page for details).", category: "advanced"}
@@ -125,6 +129,57 @@ task Annotate {
     }
 }
 
+task Filter {
+    input {
+        File vcf
+        File vcfIndex
+        String? include
+        String? exclude
+        String? softFilter
+        String outputPath = "./filtered.vcf.gz"
+
+        String memory = "256M"
+        Int timeMinutes = 1 + ceil(size(vcf, "G"))
+        String dockerImage = "quay.io/biocontainers/bcftools:1.10.2--h4f4756c_2"
+    }
+
+    command {
+        set -e 
+        mkdir -p "$(dirname ~{outputPath})"
+        bcftools \
+        filter \
+        ~{"-i " + include} \
+        ~{"-e " + exclude} \
+        ~{"-s " + softFilter} \
+        ~{vcf} \
+        -O z \
+        -o ~{outputPath}
+        bcftools index --tbi ~{outputPath}
+    }
+
+    output {
+        File outputVcf = outputPath
+        File outputVcfIndex = outputPath + ".tbi"
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        vcf: {description: "The VCF file to operate on.", category: "required"}
+        vcfIndex: {description: "The index for the VCF file.", category: "required"}
+        include: {description: "Equivalent to the `-i` option.", category: "common"}
+        outputPath: {description: "The location the output VCF file should be written.", category: "common"}
+
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.", category: "advanced"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+    }
+}
+
 task Sort {
     input {
         File inputFile
diff --git a/bedtools.wdl b/bedtools.wdl
index 3dbf93cbaea7386e9c695b658e55038173c74f6a..1d956cab25c793161adee4ff00999690a42178db 100644
--- a/bedtools.wdl
+++ b/bedtools.wdl
@@ -66,6 +66,55 @@ task Complement {
     }
 }
 
+task Coverage {
+    input {
+        File genomeFile
+        File a
+        File? aIndex
+        File b
+        File? bIndex
+        String outputPath = "./coverage.tsv"
+
+        String memory = "8G"
+        Int timeMinutes = 120
+        String dockerImage = "quay.io/biocontainers/bedtools:2.30.0--h7d7f7ad_2"
+    }
+
+    command {
+        bedtools coverage \
+        -sorted \
+        -g ~{genomeFile} \
+        -a ~{a} \
+        -b ~{b} \
+        -d \
+        > ~{outputPath}
+    }
+
+    output {
+        File coverageTsv = outputPath
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        genomeFile: {description: "A file listing the chromosomes and their lengths.", category: "required"}
+        a: {description: "The file containing the regions for which the coverage will be counted.", category: "required"}
+        aIndex: {description: "An index for the file given as `a`.", category: "common"}
+        b: {description: "The file in which the coverage will be counted. Likely a BAM file.", category: "required"}
+        bIndex: {description: "An index for the file given as `b`.", category: "common"}
+        outputPath: {description: "The path the ouptu will be written to.", category: "common"}
+
+        memory: {description: "The amount of memory needed for the job.", category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.", category: "advanced"}
+
+    }
+}
+
 task Merge {
     input {
         File inputBed
diff --git a/bwa.wdl b/bwa.wdl
index e87fd82ab7ad276b231f28bfd13fb06661339358..1cb170b70b5dc19321ea6094a31aa53418e6aab8 100644
--- a/bwa.wdl
+++ b/bwa.wdl
@@ -28,6 +28,7 @@ task Mem {
         String outputPrefix
         Boolean sixtyFour = false
         Boolean usePostalt = false
+        Boolean useSoftclippingForSupplementary = false
         Int sortMemoryPerThreadGb = 2
         Int compressionLevel = 1
 
@@ -36,7 +37,7 @@ task Mem {
 
         Int threads = 4
         Int? memoryGb
-        Int timeMinutes = 1 + ceil(size([read1, read2], "G") * 220 / threads)
+        Int timeMinutes = 10 + ceil(size([read1, read2], "G") * 300 / threads)
         # Contains bwa 0.7.17 bwakit 0.7.17.dev1 and samtools 1.10.
         String dockerImage = "quay.io/biocontainers/mulled-v2-ad317f19f5881324e963f6a6d464d696a2825ab6:c59b7a73c87a9fe81737d5d628e10a3b5807f453-0"
     }
@@ -47,7 +48,7 @@ task Mem {
     Int estimatedSortThreads = if threads == 1 then 1 else 1 + ceil(threads / 4.0)
     Int totalSortThreads = select_first([sortThreads, estimatedSortThreads])
     # BWA needs slightly more memory than the size of the index files (~10%). Add a margin for safety here.
-    Int estimatedMemoryGb = 1 + ceil(size(bwaIndex.indexFiles, "G") * 1.2) + sortMemoryPerThreadGb * totalSortThreads
+    Int estimatedMemoryGb = 10 + ceil(size(bwaIndex.indexFiles, "G") * 2) + sortMemoryPerThreadGb * totalSortThreads
     
     # The bwa postalt script is out commented as soon as usePostalt = false.
     # This hack was tested with bash, dash and ash. It seems that comments in between pipes work for all of them.
@@ -56,6 +57,7 @@ task Mem {
         mkdir -p "$(dirname ~{outputPrefix})"
         bwa mem \
           -t ~{threads} \
+          ~{if useSoftclippingForSupplementary then "-Y" else ""} \
           ~{"-R '" + readgroup}~{true="'" false="" defined(readgroup)} \
           ~{bwaIndex.fastaFile} \
           ~{read1} \
diff --git a/deconstructsigs.wdl b/deconstructsigs.wdl
new file mode 100644
index 0000000000000000000000000000000000000000..ef47e3e3d821d18ec2bbbcd46d58d87ba224f6c3
--- /dev/null
+++ b/deconstructsigs.wdl
@@ -0,0 +1,66 @@
+# Copyright (c) 2021 Leiden University Medical Center
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+version 1.0
+
+task DeconstructSigs {
+    input {
+        File signaturesMatrix
+        File signaturesReference
+        String outputPath = "./signatures.rds"
+
+        Int timeMinutes = 15
+        String memory = "4G"
+        String dockerImage = "quay.io/biocontainers/r-deconstructsigs:1.9.0--r41hdfd78af_1"
+    }
+
+    command {
+        R --no-echo << EOF
+            library(deconstructSigs)
+            tumor <- read.table("~{signaturesMatrix}", check.names=F)
+            ref <- data.frame(t(read.table("~{signaturesReference}", check.names=F, header=T, row.names="Type")), check.names=F)
+            tumor <- tumor[,colnames(ref)]
+
+            sigs <- whichSignatures(tumor.ref=tumor, row.names(tumor), signatures.ref=ref, contexts.needed=T)
+            saveRDS(sigs, "~{outputPath}")
+        EOF
+    }
+
+    output {
+        File signatureRDS = outputPath
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        signaturesMatrix: {description: "A table containing columns represtenting mutation types (matching the types in the signatures reference) and one row with the counts for each of these types for the sample of intrest.",
+                           category: "required"}
+        signaturesReference: {description: "A table describing the mutational signatures, formatted like those provided by COSMIC.",
+                              category: "required"}
+        outputPath: {description: "The location the output will be written to.", category: "common"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        memory: {description: "The amount of memory available to the job.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.", category: "advanced"}
+    }
+}
\ No newline at end of file
diff --git a/extractSigPredictHRD.wdl b/extractSigPredictHRD.wdl
new file mode 100644
index 0000000000000000000000000000000000000000..2b5d97815bc74fd35f127b1e02a7855acb6042a3
--- /dev/null
+++ b/extractSigPredictHRD.wdl
@@ -0,0 +1,71 @@
+version 1.0
+
+# Copyright (c) 2021 Leiden University Medical Center
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+task ExtractSigPredictHRD {
+    input {
+        String outputDir = "."
+        String sampleName
+        File snvIndelVcf
+        File snvIndelVcfIndex
+        File svVcf
+        File svVcfIndex
+        Boolean hg38 = false
+
+        String memory = "3G"
+        Int timeMinutes = 10
+        String dockerImage = "quay.io/biowdl/chord-mutsigextractor:2.00_1.14"
+    }
+
+    command {
+        extractSigPredictHRD.R \
+        ~{outputDir} \
+        ~{sampleName} \
+        ~{snvIndelVcf} \
+        ~{svVcf} \
+        ~{if hg38 then "RG_38" else "RG_37"}
+    }
+
+    output {
+        File chordPrediction = "~{outputDir}/~{sampleName}_chord_prediction.txt"
+        File chordSignatures = "~{outputDir}/~{sampleName}_chord_signatures.txt"
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        outputDir: {description: "The directory the outout will be written to.", category: "required"}
+        sampleName: {description: "The name of the sample.", category: "required"}
+        snvIndelVcf: {description: "A VCF file with SNVs and indels.", category: "required"}
+        snvIndelVcfIndex: {description: "The index for the SNV/indel VCF file.", category: "required"}
+        svVcf: {description: "A VCF file with SVs.", category: "required"}
+        svVcfIndex: {description: "The index for the SV VCF file.", category: "required"}
+
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
\ No newline at end of file
diff --git a/gridss.wdl b/gridss.wdl
index 5f48afac6df43a6e3eedfdbdc9c740622e954d58..7d6a1ebf028cba0b7e713f8dfb5cb997a856da51 100644
--- a/gridss.wdl
+++ b/gridss.wdl
@@ -1,6 +1,6 @@
 version 1.0
 
-# Copyright (c) 2017 Leiden University Medical Center
+# Copyright (c) 2020 Leiden University Medical Center
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,63 @@ version 1.0
 
 import "bwa.wdl" as bwa
 
+task AnnotateInsertedSequence {
+    input {
+        File inputVcf
+        String outputPath = "gridss.annotated.vcf.gz"
+        File viralReference
+        File viralReferenceFai
+        File viralReferenceDict
+        File viralReferenceImg
+
+        Int threads = 8
+        String javaXmx = "8G"
+        String memory = "9G"
+        String dockerImage = "quay.io/biowdl/gridss:2.12.2"
+        Int timeMinutes = 120
+    }
+
+    command {
+        set -e
+        _JAVA_OPTIONS="$_JAVA_OPTIONS -Xmx~{javaXmx}"
+        AnnotateInsertedSequence \
+        REFERENCE_SEQUENCE=~{viralReference} \
+        INPUT=~{inputVcf} \
+        OUTPUT=~{outputPath} \
+        ALIGNMENT=APPEND \
+        WORKING_DIR='.' \
+        WORKER_THREADS=~{threads}
+    }
+
+    output {
+        File outputVcf = outputPath
+        File outputVcfIndex = outputPath + ".tbi"
+    }
+
+    runtime {
+        cpu: threads
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        inputVcf: {description: "The input VCF file.", category: "required"}
+        outputPath: {description: "The path the output will be written to.", category: "common"}
+        viralReference: {description: "A fasta file with viral sequences.", category: "required"}
+        viralReferenceFai: {description: "The index for the viral reference fasta.", category: "required"}
+        viralReferenceDict: {description: "The dict file for the viral reference.", category: "required"}
+        viralReferenceImg: {description: "The BWA index image (generated with GATK BwaMemIndexImageCreator) of the viral reference.", category: "required"}
+
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
 task GRIDSS {
     input {
         File tumorBam
@@ -33,25 +90,31 @@ task GRIDSS {
         File? normalBam
         File? normalBai
         String? normalLabel
+        File? blacklistBed
+        File? gridssProperties
 
-        Int jvmHeapSizeGb = 30
-        Int threads = 1
-        String dockerImage = "quay.io/biocontainers/gridss:2.9.4--0"
+        Int jvmHeapSizeGb = 300
+        Int nonJvmMemoryGb = 50
+        Int threads = 4
+        Int timeMinutes = ceil(7200 / threads) + 1800
+        String dockerImage = "quay.io/biowdl/gridss:2.12.2"
     }
 
     command {
         set -e
         mkdir -p "$(dirname ~{outputPrefix})"
         gridss \
+        -w . \
         --reference ~{reference.fastaFile} \
         --output ~{outputPrefix}.vcf.gz \
         --assembly ~{outputPrefix}_assembly.bam \
+        ~{"-c " + gridssProperties} \
         ~{"-t " + threads} \
         ~{"--jvmheap " + jvmHeapSizeGb + "G"} \
-        --label ~{normalLabel}~{true="," false="" defined(normalLabel)}~{tumorLabel} \
+        --labels ~{normalLabel}~{true="," false="" defined(normalLabel)}~{tumorLabel} \
+        ~{"--blacklist " + blacklistBed} \
         ~{normalBam} \
         ~{tumorBam}
-        tabix -p vcf ~{outputPrefix}.vcf.gz
         samtools index ~{outputPrefix}_assembly.bam ~{outputPrefix}_assembly.bai
     }
 
@@ -64,7 +127,8 @@ task GRIDSS {
 
     runtime {
         cpu: threads
-        memory: "~{jvmHeapSizeGb + 1}G"
+        memory: "~{jvmHeapSizeGb + nonJvmMemoryGb}G"
+        time_minutes: timeMinutes # !UnknownRuntimeKey
         docker: dockerImage
     }
 
@@ -78,8 +142,12 @@ task GRIDSS {
         normalBam: {description: "The BAM file for the normal/control sample.", category: "advanced"}
         normalBai: {description: "The index for normalBam.", category: "advanced"}
         normalLabel: {description: "The name of the normal sample.", category: "advanced"}
-        jvmHeapSizeGb: {description: "The size of JVM heap for assembly and variant calling.",category: "advanced"}
+        blacklistBed: {description: "A bed file with blaclisted regins.", category: "advanced"}
+        gridssProperties: {description: "A properties file for gridss.", category: "advanced"}
+
         threads: {description: "The number of the threads to use.", category: "advanced"}
+        jvmHeapSizeGb: {description: "The size of JVM heap for assembly and variant calling",category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
         dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.", category: "advanced"}
 
         # outputs
@@ -89,3 +157,106 @@ task GRIDSS {
         assemblyIndex: {description: "Index of output BAM file."}
     }
 }
+
+task GridssAnnotateVcfRepeatmasker {
+    input {
+        File gridssVcf
+        File gridssVcfIndex
+        String outputPath = "./gridss.repeatmasker_annotated.vcf.gz"
+
+        String memory = "25G"
+        Int threads = 8
+        String dockerImage = "quay.io/biowdl/gridss:2.12.2"
+        Int timeMinutes = 1440
+    }
+
+    command {
+        gridss_annotate_vcf_repeatmasker \
+        --output ~{outputPath} \
+        --jar /usr/local/share/gridss-2.12.2-0/gridss.jar \
+        -w . \
+        -t ~{threads} \
+        ~{gridssVcf}
+    }
+
+    output {
+        File annotatedVcf = outputPath
+        File annotatedVcfIndex = "~{outputPath}.tbi"
+    }
+
+    runtime {
+        cpu: threads
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        gridssVcf: {description: "The GRIDSS output.", category: "required"}
+        gridssVcfIndex: {description: "The index for the GRIDSS output.", category: "required"}
+        outputPath: {description: "The path the output should be written to.", category: "common"}
+        threads: {description: "The number of the threads to use.", category: "advanced"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task Virusbreakend {
+    input {
+        File bam
+        File bamIndex
+        File referenceFasta
+        File referenceFastaFai
+        File referenceFastaDict
+        File referenceImg
+        File virusbreakendDB
+        String outputPath = "./virusbreakend.vcf"
+
+        String memory = "75G"
+        Int threads = 8
+        String dockerImage = "quay.io/biowdl/gridss:2.12.2"
+        Int timeMinutes = 180
+    }
+
+    command {
+        set -e
+        mkdir virusbreakenddb
+        tar -xzvf ~{virusbreakendDB} -C virusbreakenddb --strip-components 1
+        virusbreakend \
+        --output ~{outputPath} \
+        --workingdir . \
+        --reference ~{referenceFasta} \
+        --db virusbreakenddb \
+        --jar /usr/local/share/gridss-2.12.2-0/gridss.jar \
+        -t ~{threads} \
+        ~{bam}
+    }
+
+    output {
+        File vcf = outputPath
+        File summary = "~{outputPath}.summary.tsv"
+    }
+
+    runtime {
+        cpu: threads
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        bam: {description: "A BAM file.", category: "required"}
+        bamIndex: {description: "The index for the BAM file.", category: "required"}
+        referenceFasta: {description: "The fasta of the reference genome.", category: "required"}
+        referenceImg: {description: "The BWA index image (generated with GATK BwaMemIndexImageCreator) of the reference.", category: "required"}
+        virusbreakendDB: {description: "A .tar.gz containing the virusbreakend database.", category: "required"}
+        outputPath: {description: "The path the output should be written to.", category: "common"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        threads: {description: "The number of the threads to use.", category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
diff --git a/hmftools.wdl b/hmftools.wdl
new file mode 100644
index 0000000000000000000000000000000000000000..76620e3cc37e291d826561a13db437ae9fa13c6a
--- /dev/null
+++ b/hmftools.wdl
@@ -0,0 +1,930 @@
+version 1.0
+
+# Copyright (c) 2020 Leiden University Medical Center
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+task Amber {
+    input {
+        String referenceName
+        File referenceBam
+        File referenceBamIndex
+        String tumorName
+        File tumorBam
+        File tumorBamIndex
+        String outputDir = "./amber"
+        File loci
+        File referenceFasta
+        File referenceFastaFai
+        File referenceFastaDict
+
+        Int threads = 2
+        String memory = "70G"
+        String javaXmx = "64G"
+        Int timeMinutes = 240
+        String dockerImage = "quay.io/biocontainers/hmftools-amber:3.5--0"
+    }
+
+    command {
+        AMBER -Xmx~{javaXmx} \
+        -reference ~{referenceName} \
+        -reference_bam ~{referenceBam} \
+        -tumor ~{tumorName} \
+        -tumor_bam ~{tumorBam} \
+        -output_dir ~{outputDir} \
+        -threads ~{threads} \
+        -ref_genome ~{referenceFasta} \
+        -loci ~{loci}
+    }
+
+    output {
+        File version = "~{outputDir}/amber.version"
+        File tumorBafPcf = "~{outputDir}/~{tumorName}.amber.baf.pcf"
+        File tumorBafTsv = "~{outputDir}/~{tumorName}.amber.baf.tsv"
+        File tumorBafVcf = "~{outputDir}/~{tumorName}.amber.baf.vcf.gz"
+        File tumorBafVcfIndex = "~{outputDir}/~{tumorName}.amber.baf.vcf.gz.tbi"
+        File tumorContaminationVcf = "~{outputDir}/~{tumorName}.amber.contamination.vcf.gz"
+        File tumorContaminationVcfIndex = "~{outputDir}/~{tumorName}.amber.contamination.vcf.gz.tbi"
+        File tumorContaminationTsv = "~{outputDir}/~{tumorName}.amber.contamination.tsv"
+        File tumorQc = "~{outputDir}/~{tumorName}.amber.qc"
+        File normalSnpVcf = "~{outputDir}/~{referenceName}.amber.snp.vcf.gz"
+        File normalSnpVcfIndex = "~{outputDir}/~{referenceName}.amber.snp.vcf.gz.tbi"
+        Array[File] outputs = [version, tumorBafPcf, tumorBafTsv, tumorBafVcf, tumorBafVcfIndex, 
+            tumorContaminationVcf, tumorContaminationVcfIndex, tumorContaminationTsv, tumorQc, 
+            normalSnpVcf, normalSnpVcfIndex]
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+        cpu: threads
+    }
+
+    parameter_meta {
+        referenceName: {description: "the name of the normal sample.", category: "required"}
+        referenceBam: {description: "The normal BAM file.", category: "required"}
+        referenceBamIndex: {description: "The index for the normal BAM file.", category: "required"}
+        tumorName: {description: "The name of the tumor sample.", category: "required"}
+        tumorBam: {description: "The tumor BAM file.", category: "required"}
+        tumorBamIndex: {description: "The index for the tumor BAM file.", category: "required"}
+        outputDir: {description: "The path to the output directory.", category: "common"}
+        loci: {description: "A VCF file containing likely heterozygous sites.", category: "required"}
+        referenceFasta: {description: "The reference fasta file.", category: "required"}
+        referenceFastaDict: {description: "The sequence dictionary associated with the reference fasta file.",
+                             category: "required"}
+        referenceFastaFai: {description: "The index for the reference fasta file.", category: "required"}
+        threads: {description: "The number of threads the program will use.", category: "advanced"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task Cobalt {
+    input {
+        String referenceName
+        File referenceBam
+        File referenceBamIndex
+        String tumorName
+        File tumorBam
+        File tumorBamIndex
+        String outputDir = "./cobalt"
+        File gcProfile
+        
+        Int threads = 1
+        String memory = "5G"
+        String javaXmx = "4G"
+        Int timeMinutes = 240
+        String dockerImage = "quay.io/biocontainers/hmftools-cobalt:1.11--0"
+    }
+
+    command {
+        COBALT -Xmx~{javaXmx} \
+        -reference ~{referenceName} \
+        -reference_bam ~{referenceBam} \
+        -tumor ~{tumorName} \
+        -tumor_bam ~{tumorBam} \
+        -output_dir ~{outputDir} \
+        -threads ~{threads} \
+        -gc_profile ~{gcProfile}
+    }
+
+    output {
+        File version = "~{outputDir}/cobalt.version"
+        File normalGcMedianTsv = "~{outputDir}/~{referenceName}.cobalt.gc.median.tsv"
+        File normalRationMedianTsv = "~{outputDir}/~{referenceName}.cobalt.ratio.median.tsv"
+        File normalRationPcf = "~{outputDir}/~{referenceName}.cobalt.ratio.pcf"
+        File tumorGcMedianTsv = "~{outputDir}/~{tumorName}.cobalt.gc.median.tsv"
+        File tumorRatioPcf = "~{outputDir}/~{tumorName}.cobalt.ratio.pcf"
+        File tumorRatioTsv = "~{outputDir}/~{tumorName}.cobalt.ratio.tsv"
+        File tumorChrLen = "~{outputDir}/~{tumorName}.chr.len"
+        Array[File] outputs = [version, normalGcMedianTsv, normalRationMedianTsv,
+            normalRationPcf, tumorGcMedianTsv, tumorRatioPcf, tumorRatioTsv, tumorChrLen]
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+        cpu: threads
+    }
+
+    parameter_meta {
+        referenceName: {description: "the name of the normal sample.", category: "required"}
+        referenceBam: {description: "The normal BAM file.", category: "required"}
+        referenceBamIndex: {description: "The index for the normal BAM file.", category: "required"}
+        tumorName: {description: "The name of the tumor sample.", category: "required"}
+        tumorBam: {description: "The tumor BAM file.", category: "required"}
+        tumorBamIndex: {description: "The index for the tumor BAM file.", category: "required"}
+        outputDir: {description: "The path to the output directory.", category: "common"}
+        gcProfile: {description: "A file describing the GC profile of the reference genome.", category: "required"}
+        threads: {description: "The number of threads the program will use.", category: "advanced"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task Cuppa {
+    input {
+        Array[File]+ linxOutput
+        Array[File]+ purpleOutput
+        String sampleName
+        Array[String]+ categories = ["DNA"]
+        Array[File]+ referenceData 
+        File purpleSvVcf
+        File purpleSvVcfIndex
+        File purpleSomaticVcf
+        File purpleSomaticVcfIndex
+        String outputDir = "./cuppa"
+
+        String javaXmx = "4G"
+        String memory = "5G"
+        Int timeMinutes = 10
+        String dockerImage = "quay.io/biowdl/cuppa:1.4"
+    }
+
+    command {
+        set -e
+        mkdir -p sampleData ~{outputDir}
+        ln -s -t sampleData ~{sep=" " linxOutput} ~{sep=" " purpleOutput}
+        cuppa -Xmx~{javaXmx} \
+        -output_dir ~{outputDir} \
+        -output_id ~{sampleName} \
+        -categories '~{sep="," categories}' \
+        -ref_data_dir ~{sub(referenceData[0], basename(referenceData[0]), "")} \
+        -sample_data_dir sampleData \
+        -sample_data ~{sampleName} \
+        -sample_sv_file ~{purpleSvVcf} \
+        -sample_somatic_vcf ~{purpleSomaticVcf}
+    }
+
+    output {
+        File cupData = "~{outputDir}/~{sampleName}.cup.data.csv"
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        linxOutput: {description: "The files produced by linx.", category: "required"}
+        purpleOutput: {description: "The files produced by purple.", category: "required"}
+        sampleName: {description: "The name of the sample.", category: "required"}
+        categories: {description: "The classifiers to use.", category: "advanced"}
+        referenceData : {description: "The reference data.", category: "required"}
+        purpleSvVcf: {description: "The VCF file produced by purple which contains structural variants.", category: "required"}
+        purpleSvVcfIndex: {description: "The index of the structural variants VCF file produced by purple.", category: "required"}
+        purpleSomaticVcf: {description: "The VCF file produced by purple which contains somatic variants.", category: "required"}
+        purpleSomaticVcfIndex: {description: "The index of the somatic VCF file produced by purple.", category: "required"}
+        outputDir: {description: "The directory the ouput will be placed in.", category: "common"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task CuppaChart {
+    input {
+        String sampleName
+        File cupData
+        String outputDir = "./cuppa"
+
+        String memory = "4G"
+        Int timeMinutes = 5
+        String dockerImage = "quay.io/biowdl/cuppa:1.4"
+    }
+
+    command {
+        set -e 
+        mkdir -p ~{outputDir}
+        cuppa-chart \
+        -sample ~{sampleName} \
+        -sample_data ~{cupData} \
+        -output_dir ~{outputDir}
+    }
+
+    output {
+        File cuppaChart = "~{outputDir}/~{sampleName}.cuppa.chart.png"
+        File cuppaConclusion = "~{outputDir}/~{sampleName}.cuppa.conclusion.txt"
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        sampleName: {description: "The name of the sample.", category:"common"}
+        cupData: {description: "The cuppa output.", category: "required"}
+        outputDir: {description: "The directory the output will be written to.", category:"common"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task GripssApplicationKt {
+    input {
+        File inputVcf
+        String outputPath = "gripss.vcf.gz"
+        String tumorName
+        String referenceName
+        File referenceFasta
+        File referenceFastaFai
+        File referenceFastaDict
+        File breakpointHotspot
+        File breakendPon
+        File breakpointPon
+
+        String memory = "32G"
+        String javaXmx = "31G"
+        Int timeMinutes = 45
+        String dockerImage = "quay.io/biocontainers/hmftools-gripss:1.11--hdfd78af_0"
+    }
+
+    command {
+        java -Xmx~{javaXmx} -XX:ParallelGCThreads=1 \
+        -cp /usr/local/share/hmftools-gripss-1.11-0/gripss.jar \
+        com.hartwig.hmftools.gripss.GripssApplicationKt \
+        -tumor ~{tumorName} \
+        -reference ~{referenceName} \
+        -ref_genome ~{referenceFasta} \
+        -breakpoint_hotspot ~{breakpointHotspot} \
+        -breakend_pon ~{breakendPon} \
+        -breakpoint_pon ~{breakpointPon} \
+        -input_vcf ~{inputVcf} \
+        -output_vcf ~{outputPath} \
+        -paired_normal_tumor_ordinals
+    }
+
+    output {
+        File outputVcf = outputPath
+        File outputVcfIndex = outputPath + ".tbi"
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        inputVcf: {description: "The input VCF.", category: "required"}
+        outputPath: {description: "The path where th eoutput VCF will be written.", category: "common"}
+        referenceFasta: {description: "The reference fasta file.", category: "required"}
+        referenceFastaDict: {description: "The sequence dictionary associated with the reference fasta file.",
+                             category: "required"}
+        referenceFastaFai: {description: "The index for the reference fasta file.", category: "required"}
+        breakpointHotspot: {description: "Equivalent to the `-breakpoint_hotspot` option.", category: "required"}
+        breakendPon: {description: "Equivalent to the `-breakend_pon` option.", category: "required"}
+        breakpointPon: {description: "Equivalent to the `breakpoint_pon` option.", category: "required"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task GripssHardFilterApplicationKt {
+    input {
+        File inputVcf
+        String outputPath = "gripss_hard_filter.vcf.gz"
+
+        String memory = "3G"
+        String javaXmx = "2G"
+        Int timeMinutes = 15
+        String dockerImage = "quay.io/biocontainers/hmftools-gripss:1.11--hdfd78af_0"
+    }
+
+    command {
+        java -Xmx~{javaXmx} -XX:ParallelGCThreads=1 \
+        -cp /usr/local/share/hmftools-gripss-1.11-0/gripss.jar \
+        com.hartwig.hmftools.gripss.GripssHardFilterApplicationKt \
+        -input_vcf ~{inputVcf} \
+        -output_vcf ~{outputPath} 
+    }
+
+    output {
+        File outputVcf = outputPath
+        File outputVcfIndex = outputPath + ".tbi"
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        inputVcf: {description: "The input VCF.", category: "required"}
+        outputPath: {description: "The path where th eoutput VCF will be written.", category: "common"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task HealthChecker {
+    input {
+        String outputDir = "."
+        String referenceName
+        File referenceFlagstats
+        File referenceMetrics
+        String tumorName
+        File tumorFlagstats
+        File tumorMetrics
+        Array[File]+ purpleOutput
+
+        String javaXmx = "2G"
+        String memory = "1G"
+        Int timeMinutes = 1
+        String dockerImage = "quay.io/biowdl/health-checker:3.2"
+    }
+
+    command {
+        set -e
+        mkdir -p ~{outputDir}
+        health-checker -Xmx~{javaXmx} -XX:ParallelGCThreads=1 \
+        -reference ~{referenceName} \
+        -ref_flagstat_file ~{referenceFlagstats} \
+        -ref_wgs_metrics_file ~{referenceMetrics} \
+        -tumor ~{tumorName} \
+        -tum_flagstat_file ~{tumorFlagstats} \
+        -tum_wgs_metrics_file ~{tumorMetrics} \
+        -purple_dir ~{sub(purpleOutput[0], basename(purpleOutput[0]), "")} \
+        -output_dir ~{outputDir}
+        test -e '~{outputDir}/~{tumorName}.HealthCheckSucceeded' && echo 'true' > '~{outputDir}/succeeded'
+        test -e '~{outputDir}/~{tumorName}.HealthCheckFailed' && echo 'false' > '~{outputDir}/succeeded'
+    }
+
+    output {
+        Boolean succeeded = read_boolean("result")
+        File outputFile = if succeeded 
+                          then "~{outputDir}/~{tumorName}.HealthCheckSucceeded"
+                          else "~{outputDir}/~{tumorName}.HealthCheckFailed"
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        outputDir: {description: "The path the output will be written to.", category:"required"}
+        referenceName: {description: "The name of the normal sample.", category: "required"}
+        referenceFlagstats: {description: "The flagstats for the normal sample.", category: "required"}
+        referenceMetrics: {description: "The picard WGS metrics for the normal sample.", category: "required"}
+        tumorName: {description: "The name of the tumor sample.", category: "required"}
+        tumorFlagstats: {description: "The flagstats for the tumor sample.", category: "required"}
+        tumorMetrics: {description: "The picard WGS metrics for the tumor sample.", category: "required"}
+        purpleOutput: {description: "The files from purple's output directory.", category: "required"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task Linx {
+    input {
+        String sampleName
+        File svVcf
+        File svVcfIndex
+        Array[File]+ purpleOutput
+        String refGenomeVersion
+        String outputDir = "./linx"
+        File fragileSiteCsv
+        File lineElementCsv
+        File replicationOriginsBed
+        File viralHostsCsv
+        File knownFusionCsv
+        File driverGenePanel
+        #The following should be in the same directory.
+        File geneDataCsv
+        File proteinFeaturesCsv
+        File transExonDataCsv
+        File transSpliceDataCsv
+
+        String memory = "5G"
+        String javaXmx = "4G"
+        Int timeMinutes = 10
+        String dockerImage = "quay.io/biocontainers/hmftools-linx:1.16--hdfd78af_0"
+    }
+
+    command {
+        linx -Xmx~{javaXmx} -XX:ParallelGCThreads=1 \
+        -sample ~{sampleName} \
+        -sv_vcf ~{svVcf} \
+        -purple_dir ~{sub(purpleOutput[0], basename(purpleOutput[0]), "")} \
+        -ref_genome_version ~{refGenomeVersion} \
+        -output_dir ~{outputDir} \
+        -fragile_site_file ~{fragileSiteCsv} \
+        -line_element_file ~{lineElementCsv} \
+        -replication_origins_file ~{replicationOriginsBed} \
+        -viral_hosts_file ~{viralHostsCsv} \
+        -gene_transcripts_dir ~{sub(geneDataCsv, basename(geneDataCsv), "")} \
+        -check_fusions \
+        -known_fusion_file ~{knownFusionCsv} \
+        -check_drivers \
+        -driver_gene_panel ~{driverGenePanel} \
+        -chaining_sv_limit 0 \
+        -write_vis_data
+    }
+
+    output {
+        File driverCatalog = "~{outputDir}/~{sampleName}.linx.driver.catalog.tsv"
+        File linxBreakend = "~{outputDir}/~{sampleName}.linx.breakend.tsv"
+        File linxClusters = "~{outputDir}/~{sampleName}.linx.clusters.tsv"
+        File linxDrivers = "~{outputDir}/~{sampleName}.linx.drivers.tsv"
+        File linxFusion = "~{outputDir}/~{sampleName}.linx.fusion.tsv"
+        File linxLinks = "~{outputDir}/~{sampleName}.linx.links.tsv"
+        File linxSvs = "~{outputDir}/~{sampleName}.linx.svs.tsv"
+        File linxViralInserts = "~{outputDir}/~{sampleName}.linx.viral_inserts.tsv"
+        File linxVisCopyNumber = "~{outputDir}/~{sampleName}.linx.vis_copy_number.tsv"
+        File linxVisFusion = "~{outputDir}/~{sampleName}.linx.vis_fusion.tsv"
+        File linxVisGeneExon = "~{outputDir}/~{sampleName}.linx.vis_gene_exon.tsv"
+        File linxVisProteinDomain = "~{outputDir}/~{sampleName}.linx.vis_protein_domain.tsv"
+        File linxVisSegments = "~{outputDir}/~{sampleName}.linx.vis_segments.tsv"
+        File linxVisSvData = "~{outputDir}/~{sampleName}.linx.vis_sv_data.tsv"
+        File linxVersion = "~{outputDir}/linx.version"
+        Array[File] outputs = [driverCatalog, linxBreakend, linxClusters, linxDrivers, linxFusion,
+                               linxLinks, linxSvs, linxViralInserts, linxVisCopyNumber,
+                               linxVisFusion, linxVisGeneExon, linxVisProteinDomain,
+                               linxVisSegments, linxVisSvData, linxVersion]
+    }
+
+    runtime {
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+        memory: memory
+    }
+
+    parameter_meta {
+        sampleName: {description: "The name of the sample.", category: "required"}
+        svVcf: {description: "A VCF file containing structural variants, produced using GRIDSS, annotated for viral insertions and postprocessed with GRIPSS.", category: "required"}
+        svVcfIndex: {description: "Index for the structural variants VCf file.", category: "required"}
+        purpleOutput: {description: "The files produced by PURPLE.", category: "required"}
+        refGenomeVersion: {description: "The version of the genome assembly used for alignment. Either \"HG19\" or \"HG38\".", category: "required"}
+        outputDir: {description: "The directory the outputs will be written to.", category: "required"}
+        fragileSiteCsv: {description: "A list of known fragile sites.", category: "required"}
+        lineElementCsv: {description: "A list of known LINE source regions.", category: "required"}
+        replicationOriginsBed: {description: "Replication timing input in BED format with replication timing as the 4th column.", category: "required"}
+        viralHostsCsv: {description: "A list of the viruses which were used for annotation of the GRIDSS results.", category: "required"}
+        knownFusionCsv: {description: "A CSV file describing known fusions.", category: "required"}
+        driverGenePanel: {description: "A TSV file describing the driver gene panel.", category: "required"}
+        geneDataCsv: {description: "A  CSV file containing gene information, must be in the same directory as `proteinFeaturesCsv`, `transExonDataCsv` and `transSpliceDataCsv`.", category: "required"}
+        proteinFeaturesCsv: {description: "A  CSV file containing protein feature information, must be in the same directory as `geneDataCsv`, `transExonDataCsv` and `transSpliceDataCsv`.", category: "required"}
+        transExonDataCsv: {description: "A  CSV file containing transcript exon information, must be in the same directory as `geneDataCsv`, `proteinFeaturesCsv` and `transSpliceDataCsv`.", category: "required"}
+        transSpliceDataCsv: {description: "A  CSV file containing transcript splicing information, must be in the same directory as `geneDataCsv`, `proteinFeaturesCsv` and `transExonDataCsv`.", category: "required"}
+
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task Protect {
+    input {
+        String refGenomeVersion
+        String tumorName
+        String referenceName
+        Array[String]+ sampleDoids
+        String outputDir = "."
+        Array[File]+ serveActionability
+        File doidJson
+        File purplePurity
+        File purpleQc
+        File purpleDriverCatalogSomatic
+        File purpleDriverCatalogGermline
+        File purpleSomaticVariants
+        File purpleSomaticVariantsIndex
+        File purpleGermlineVariants
+        File purpleGermlineVariantsIndex
+        File purpleGeneCopyNumber
+        File linxFusion
+        File linxBreakend
+        File linxDriversCatalog
+        File chordPrediction
+        File annotatedVirus
+
+        String memory = "9G"
+        String javaXmx = "8G"
+        Int timeMinutes = 60
+        String dockerImage = "quay.io/biowdl/protect:v1.4"
+    }
+
+    command {
+        protect -Xmx~{javaXmx} \
+        -ref_genome_version ~{refGenomeVersion} \
+        -tumor_sample_id ~{tumorName} \
+        -reference_sample_id ~{referenceName} \
+        -primary_tumor_doids '~{sep=";" sampleDoids}' \
+        -output_dir ~{outputDir} \
+        -serve_actionability_dir ~{sub(serveActionability[0], basename(serveActionability[0]), "")} \
+        -doid_json ~{doidJson} \
+        -purple_purity_tsv ~{purplePurity} \
+        -purple_qc_file ~{purpleQc} \
+        -purple_somatic_driver_catalog_tsv ~{purpleDriverCatalogSomatic} \
+        -purple_germline_driver_catalog_tsv ~{purpleDriverCatalogGermline} \
+        -purple_somatic_variant_vcf ~{purpleSomaticVariants} \
+        -purple_germline_variant_vcf ~{purpleGermlineVariants} \
+        -purple_gene_copy_number_tsv ~{purpleGeneCopyNumber} \
+        -linx_fusion_tsv ~{linxFusion} \
+        -linx_breakend_tsv ~{linxBreakend} \
+        -linx_driver_catalog_tsv ~{linxDriversCatalog} \
+        -chord_prediction_txt ~{chordPrediction} \
+        -annotated_virus_tsv ~{annotatedVirus}
+    }
+
+    output {
+        File protectTsv = "~{outputDir}/~{tumorName}.protect.tsv"
+    }
+
+    runtime {
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+        memory: memory
+    }
+
+    parameter_meta {
+        refGenomeVersion: {description: "The version of the genome assembly used for alignment. Either \"37\" or \"38\".", category: "required"} 
+        tumorName: {description: "The name of the tumor sample.", category: "required"}
+        referenceName: {description: "The name of the normal sample.", category: "required"}
+        sampleDoids: {description: "The DOIDs (Human Disease Ontology) for the primary tumor.", category: "required"}
+        outputDir: {description: "The directory the outputs will be written to.", category: "required"}
+        serveActionability: {description: "The actionability files generated by hmftools' serve.", category: "required"}
+        doidJson: {description: "A json with the DOID (Human Disease Ontology) tree.", category: "required"}
+        purplePurity: {description: "The purity file generated by purple.", category: "required"}
+        purpleQc: {description: "The QC file generated by purple.", category: "required"}
+        purpleDriverCatalogSomatic: {description: "The somatic driver catalog generated by purple.", category: "required"}
+        purpleDriverCatalogGermline: {description: "The germline driver catalog generated by purple.", category: "required"}
+        purpleSomaticVariants: {description: "The somatic VCF generated by purple.", category: "required"}
+        purpleSomaticVariantsIndex: {description: "The index for the somatic VCF generated by purple.", category: "required"}
+        purpleGermlineVariants: {description: "The germline VCF generated by purple.", category: "required"}
+        purpleGermlineVariantsIndex: {description: "The index of the germline VCF generated by purple.", category: "required"}
+        purpleGeneCopyNumber: {description: "The gene copy number file generated by purple.", category: "required"}
+        linxFusion: {description: "The fusion file generated by linx.", category: "required"}
+        linxBreakend: {description: "The breakend file generated by linx.", category: "required"}
+        linxDriversCatalog: {description: "The driver catalog generated generated by linx.", category: "required"}
+        chordPrediction: {description: "The chord prediction file.", category: "required"}
+        annotatedVirus: {description: "The virus-interpreter output.", category: "required"}
+
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task Purple {
+    input {
+        String referenceName
+        String tumorName
+        String outputDir = "./purple"
+        Array[File]+ amberOutput
+        Array[File]+ cobaltOutput
+        File gcProfile
+        File somaticVcf
+        File germlineVcf
+        File filteredSvVcf
+        File? fullSvVcf
+        File? fullSvVcfIndex
+        File referenceFasta
+        File referenceFastaFai
+        File referenceFastaDict
+        File driverGenePanel
+        File somaticHotspots
+        File germlineHotspots
+        
+        Int threads = 1
+        Int timeMinutes = 30
+        String memory = "9G"
+        String javaXmx = "8G"
+        # clone of quay.io/biocontainers/hmftools-purple:3.1--hdfd78af_0 with 'ln -s /usr/local/lib/libwebp.so.7 /usr/local/lib/libwebp.so.6'
+        String dockerImage = "quay.io/biowdl/hmftools-purple:3.1" 
+    }
+
+    command {
+        PURPLE -Xmx~{javaXmx} \
+        -reference ~{referenceName} \
+        -tumor ~{tumorName} \
+        -output_dir ~{outputDir} \
+        -amber ~{sub(amberOutput[0], basename(amberOutput[0]), "")} \
+        -cobalt ~{sub(cobaltOutput[0], basename(cobaltOutput[0]), "")} \
+        -gc_profile ~{gcProfile} \
+        -somatic_vcf ~{somaticVcf} \
+        -germline_vcf ~{germlineVcf} \
+        -structural_vcf ~{filteredSvVcf} \
+        ~{"-sv_recovery_vcf " + fullSvVcf} \
+        -circos /usr/local/bin/circos \
+        -ref_genome ~{referenceFasta} \
+        -driver_catalog \
+        -driver_gene_panel ~{driverGenePanel} \
+        -somatic_hotspots ~{somaticHotspots} \
+        -germline_hotspots ~{germlineHotspots} \
+        -threads ~{threads}
+    }
+
+    output {
+        File driverCatalogSomaticTsv = "~{outputDir}/~{tumorName}.driver.catalog.somatic.tsv"
+        File driverCatalogGermlineTsv = "~{outputDir}/~{tumorName}.driver.catalog.germline.tsv"
+        File purpleCnvGeneTsv = "~{outputDir}/~{tumorName}.purple.cnv.gene.tsv"
+        File purpleCnvGermlineTsv = "~{outputDir}/~{tumorName}.purple.cnv.germline.tsv"
+        File purpleCnvSomaticTsv = "~{outputDir}/~{tumorName}.purple.cnv.somatic.tsv"
+        File purplePurityRangeTsv = "~{outputDir}/~{tumorName}.purple.purity.range.tsv"
+        File purplePurityTsv = "~{outputDir}/~{tumorName}.purple.purity.tsv"
+        File purpleQc = "~{outputDir}/~{tumorName}.purple.qc"
+        File purpleSegmentTsv = "~{outputDir}/~{tumorName}.purple.segment.tsv"
+        File purpleSomaticClonalityTsv = "~{outputDir}/~{tumorName}.purple.somatic.clonality.tsv"
+        File purpleSomaticHistTsv = "~{outputDir}/~{tumorName}.purple.somatic.hist.tsv"
+        File purpleSomaticVcf = "~{outputDir}/~{tumorName}.purple.somatic.vcf.gz"
+        File purpleSomaticVcfIndex = "~{outputDir}/~{tumorName}.purple.somatic.vcf.gz.tbi"
+        File purpleGermlineVcf = "~{outputDir}/~{tumorName}.purple.germline.vcf.gz"
+        File purpleGermlineVcfIndex = "~{outputDir}/~{tumorName}.purple.germline.vcf.gz.tbi"
+        File purpleSvVcf = "~{outputDir}/~{tumorName}.purple.sv.vcf.gz"
+        File purpleSvVcfIndex = "~{outputDir}/~{tumorName}.purple.sv.vcf.gz.tbi"
+        File circosPlot = "~{outputDir}/plot/~{tumorName}.circos.png"
+        File copynumberPlot = "~{outputDir}/plot/~{tumorName}.copynumber.png"
+        File inputPlot = "~{outputDir}/plot/~{tumorName}.input.png"
+        File mapPlot = "~{outputDir}/plot/~{tumorName}.map.png"
+        File purityRangePlot = "~{outputDir}/plot/~{tumorName}.purity.range.png"
+        File segmentPlot = "~{outputDir}/plot/~{tumorName}.segment.png"
+        File somaticClonalityPlot = "~{outputDir}/plot/~{tumorName}.somatic.clonality.png"
+        File somaticPlot = "~{outputDir}/plot/~{tumorName}.somatic.png"
+        File purpleVersion = "~{outputDir}/purple.version"
+        File circosNormalRatio = "~{outputDir}/circos/~{referenceName}.ratio.circos"
+        File circosConf = "~{outputDir}/circos/~{tumorName}.circos.conf"
+        File circosIndel = "~{outputDir}/circos/~{tumorName}.indel.circos"
+        File circosLink = "~{outputDir}/circos/~{tumorName}.link.circos"
+        File circosTumorRatio = "~{outputDir}/circos/~{tumorName}.ratio.circos"
+        File circosGaps = "~{outputDir}/circos/gaps.txt"
+        File circosBaf = "~{outputDir}/circos/~{tumorName}.baf.circos"
+        File circosCnv = "~{outputDir}/circos/~{tumorName}.cnv.circos"
+        File circosInputConf = "~{outputDir}/circos/~{tumorName}.input.conf"
+        File circosMap = "~{outputDir}/circos/~{tumorName}.map.circos"
+        File circosSnp = "~{outputDir}/circos/~{tumorName}.snp.circos"
+        Array[File] outputs = [driverCatalogSomaticTsv, purpleCnvGeneTsv, purpleCnvGermlineTsv,
+            purpleCnvSomaticTsv, purplePurityRangeTsv, purplePurityTsv, purpleQc, 
+            purpleSegmentTsv, purpleSomaticClonalityTsv, purpleSomaticHistTsv, 
+            purpleSomaticVcf, purpleSomaticVcfIndex, purpleSvVcf, purpleSvVcfIndex,
+            purpleVersion, purpleGermlineVcf, purpleGermlineVcfIndex, driverCatalogGermlineTsv]
+        Array[File] plots = [circosPlot, copynumberPlot, inputPlot, mapPlot, purityRangePlot,
+            segmentPlot, somaticClonalityPlot, somaticPlot]
+        Array[File] circos = [circosNormalRatio, circosConf, circosIndel, circosLink,
+            circosTumorRatio, circosGaps, circosBaf, circosCnv, circosInputConf, circosMap,
+            circosSnp]
+    }
+
+    runtime {
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        cpu: threads
+        docker: dockerImage
+        memory: memory
+    }
+
+    parameter_meta {
+        referenceName: {description: "the name of the normal sample.", category: "required"}
+        tumorName: {description: "The name of the tumor sample.", category: "required"}
+        outputDir: {description: "The path to the output directory.", category: "common"}
+        amberOutput: {description: "The output files of hmftools amber.", category: "required"}
+        cobaltOutput: {description: "The output files of hmftools cobalt", category: "required"}
+        gcProfile: {description: "A file describing the GC profile of the reference genome.", category: "required"}
+        somaticVcf: {description: "The somatic variant calling results.", category: "required"}
+        germlineVcf: {description: "The germline variant calling results.", category: "required"}
+        filteredSvVcf: {description: "The filtered structural variant calling results.", category: "required"}
+        fullSvVcf: {description: "The unfiltered structural variant calling results.", category: "required"}
+        referenceFasta: {description: "The reference fasta file.", category: "required"}
+        referenceFastaDict: {description: "The sequence dictionary associated with the reference fasta file.",
+                             category: "required"}
+        referenceFastaFai: {description: "The index for the reference fasta file.", category: "required"}
+        driverGenePanel: {description: "A TSV file describing the driver gene panel.", category: "required"}
+        somaticHotspots: {description: "A vcf file with hotspot somatic variant sites.", category: "required"}
+        germlineHotspots: {description: "A vcf file with hotspot germline variant sites.", category: "required"}
+
+        threads: {description: "The number of threads the program will use.", category: "advanced"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task Sage {
+    input {
+        String tumorName
+        File tumorBam
+        File tumorBamIndex
+        File referenceFasta
+        File referenceFastaDict
+        File referenceFastaFai
+        File hotspots
+        File panelBed
+        File highConfidenceBed
+        Boolean hg38 = false
+        Boolean panelOnly = false
+        String outputPath = "./sage.vcf.gz"
+
+        String? referenceName
+        File? referenceBam
+        File? referenceBamIndex
+        Int? hotspotMinTumorQual
+        Int? panelMinTumorQual
+        Int? hotspotMaxGermlineVaf
+        Int? hotspotMaxGermlineRelRawBaseQual
+        Int? panelMaxGermlineVaf
+        Int? panelMaxGermlineRelRawBaseQual
+        String? mnvFilterEnabled
+        File? coverageBed
+
+        Int threads = 4
+        String javaXmx = "50G"
+        String memory = "51G"
+        Int timeMinutes = 1 + ceil(size(select_all([tumorBam, referenceBam]), "G") * 9 / threads)
+        String dockerImage = "quay.io/biocontainers/hmftools-sage:2.8--hdfd78af_0"
+    }
+
+    command {
+        SAGE -Xmx~{javaXmx} -XX:ParallelGCThreads=1 \
+        -tumor ~{tumorName} \
+        -tumor_bam ~{tumorBam} \
+        ~{"-reference " + referenceName} \
+        ~{"-reference_bam " + referenceBam} \
+        -ref_genome ~{referenceFasta} \
+        -hotspots ~{hotspots} \
+        -panel_bed ~{panelBed} \
+        -high_confidence_bed ~{highConfidenceBed} \
+        -assembly ~{true="hg38" false="hg19" hg38} \
+        ~{"-hotspot_min_tumor_qual " + hotspotMinTumorQual} \
+        ~{"-panel_min_tumor_qual " + panelMinTumorQual} \
+        ~{"-hotspot_max_germline_vaf " + hotspotMaxGermlineVaf} \
+        ~{"-hotspot_max_germline_rel_raw_base_qual " + hotspotMaxGermlineRelRawBaseQual} \
+        ~{"-panel_max_germline_vaf " + panelMaxGermlineVaf} \
+        ~{"-panel_max_germline_rel_raw_base_qual " + panelMaxGermlineRelRawBaseQual} \
+        ~{"-mnv_filter_enabled " + mnvFilterEnabled} \
+        ~{"-coverage_bed " + coverageBed} \
+        ~{true="-panel_only" false="" panelOnly} \
+        -threads ~{threads} \
+        -out ~{outputPath}
+    }
+
+    output {
+        File outputVcf = outputPath
+        File outputVcfIndex = outputPath + ".tbi"
+        # There is some plots as well, but in the current container the labels in the plots are just series of `â–¡`s.
+        # This seems to be a systemic issue with R generated plots in biocontainers...
+    }
+
+    runtime {
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        cpu: threads
+        docker: dockerImage
+        memory: memory
+    }
+
+    parameter_meta {
+        tumorName: {description: "The name of the tumor sample.", category: "required"}
+        tumorBam: {description: "The BAM file for the tumor sample.", category: "required"}
+        tumorBamIndex: {description: "The index of the BAM file for the tumor sample.", category: "required"}
+        referenceName: {description: "The name of the normal/reference sample.", category: "common"}
+        referenceBam: {description: "The BAM file for the normal sample.", category: "common"}
+        referenceBamIndex: {description: "The index of the BAM file for the normal sample.", category: "common"}
+        referenceFasta: {description: "The reference fasta file.", category: "required"}
+        referenceFastaDict: {description: "The sequence dictionary associated with the reference fasta file.",
+                             category: "required"}
+        referenceFastaFai: {description: "The index for the reference fasta file.", category: "required"}
+        hotspots: {description: "A vcf file with hotspot variant sites.", category: "required"}
+        panelBed: {description: "A bed file describing coding regions to search for in frame indels.", category: "required"}
+        highConfidenceBed: {description: "A bed files describing high confidence mapping regions.", category: "required"}
+        hotspotMinTumorQual: {description: "Equivalent to sage's `hotspot_min_tumor_qual` option.", category: "advanced"}
+        panelMinTumorQual: {description: "Equivalent to sage's `panel_min_tumor_qual` option.", category: "advanced"}
+        hotspotMaxGermlineVaf: {description: "Equivalent to sage's `hotspot_max_germline_vaf` option.", category: "advanced"}
+        hotspotMaxGermlineRelRawBaseQual: {description: "Equivalent to sage's `hotspot_max_germline_rel_raw_base_qual` option.", category: "advanced"}
+        panelMaxGermlineVaf: {description: "Equivalent to sage's `panel_max_germline_vaf` option.", category: "advanced"}
+        panelMaxGermlineRelRawBaseQual: {description: "Equivalent to sage's `panel_max_germline_vaf` option.", category: "advanced"}
+        mnvFilterEnabled: {description: "Equivalent to sage's `mnv_filter_enabled` option.", category: "advanced"}
+
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
+task VirusInterpreter {
+    input {
+        String sampleId
+        File virusBreakendTsv
+        File taxonomyDbTsv
+        File virusInterpretationTsv
+        File virusBlacklistTsv
+        String outputDir = "."
+
+        String memory = "3G"
+        String javaXmx = "2G"
+        Int timeMinutes = 15
+        String dockerImage = "quay.io/biowdl/virus-interpreter:1.0"
+    }
+
+    command {
+        virus-interpreter -Xmx~{javaXmx} \
+        -sample_id ~{sampleId} \
+        -virus_breakend_tsv ~{virusBreakendTsv} \
+        -taxonomy_db_tsv ~{taxonomyDbTsv} \
+        -virus_interpretation_tsv ~{virusInterpretationTsv} \
+        -virus_blacklist_tsv ~{virusBlacklistTsv} \
+        -output_dir ~{outputDir}
+    }
+
+    output {
+        File virusAnnotatedTsv = "~{outputDir}/~{sampleId}.virus.annotated.tsv"
+    }
+
+    runtime {
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+        memory: memory
+    }
+
+    parameter_meta {
+        sampleId: {description: "The name of the sample.", category: "required"}
+        virusBreakendTsv: {description: "The TSV output from virusbreakend.", category: "required"}
+        taxonomyDbTsv: {description: "A taxonomy database tsv.", category: "required"}
+        virusInterpretationTsv: {description: "A virus interpretation tsv.", category: "required"}
+        virusBlacklistTsv: {description: "A virus blacklist tsv.", category: "required"}
+        outputDir: {description: "The directory the output will be written to.", category: "required"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
diff --git a/peach.wdl b/peach.wdl
new file mode 100644
index 0000000000000000000000000000000000000000..af44daecfc342630d78866d93767b260147d1a0e
--- /dev/null
+++ b/peach.wdl
@@ -0,0 +1,77 @@
+version 1.0
+
+# Copyright (c) 2021 Leiden University Medical Center
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+task Peach {
+    input {
+        File transcriptTsv
+        File germlineVcf
+        File germlineVcfIndex
+        String tumorName
+        String normalName
+        String outputDir = "./peach"
+        File panelJson
+
+        String memory = "2G"
+        String dockerImage = "quay.io/biowdl/peach:v1.0"
+        Int timeMinutes = 5
+    }
+
+    command {
+        peach \
+        --recreate_bed \
+        --transcript_tsv ~{transcriptTsv} \
+        ~{germlineVcf} \
+        ~{tumorName} \
+        ~{normalName} \
+        1.0 \
+        ~{outputDir} \
+        ~{panelJson} \
+        vcftools
+    }
+
+    output {
+        File callsTsv = "~{outputDir}/~{tumorName}.peach.calls.tsv"
+        File filteredVcf = "~{outputDir}/~{tumorName}.peach.filtered.vcf"
+        File genotypeTsv = "~{outputDir}/~{tumorName}.peach.genotype.tsv"
+        Array[File] outputs = [callsTsv, filteredVcf, genotypeTsv]
+    }
+
+    runtime {
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        transcriptTsv: {description: "A tsv file describing transcripts.", category: "required"}
+        germlineVcf: {description: "The germline VCF file from hmftools' purple.", category: "required"}
+        germlineVcfIndex: {description: "The germline VCF's index.", category: "required"}
+        tumorName: {description: "The name of the tumor sample.", category: "required"}
+        normalName: {description: "The name of the normal sample", category: "required"}
+        outputDir: {description: "The directory the ouput should be written to.", category: "required"}
+        panelJson: {description: "A JSON describing the panel.", category: "required"}
+
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        memory: {description: "The amount of memory available to the job.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.", category: "advanced"}
+    }
+}
\ No newline at end of file
diff --git a/picard.wdl b/picard.wdl
index f75fdc326133675c7a95286a14c09cba8079987c..9a935045bd9804ce37f7773b5f8db480fa3563b2 100644
--- a/picard.wdl
+++ b/picard.wdl
@@ -446,6 +446,70 @@ task CollectVariantCallingMetrics {
     }
 }
 
+task CollectWgsMetrics {
+    input {
+        File inputBam
+        File inputBamIndex
+        File referenceFasta
+        File referenceFastaDict
+        File referenceFastaFai
+        String outputPath = "./wgs_metrics.txt"
+        
+        Int? minimumMappingQuality
+        Int? minimumBaseQuality
+        Int? coverageCap
+
+        String memory = "5G"
+        String javaXmx = "4G"
+        Int timeMinutes = 1 + ceil(size(inputBam, "G") * 6)
+        String dockerImage = "quay.io/biocontainers/picard:2.23.2--0"
+    }
+
+    command {
+        set -e
+        mkdir -p "$(dirname ~{outputPath})"
+
+        picard -Xmx~{javaXmx} -XX:ParallelGCThreads=1 \
+        CollectWgsMetrics \
+        REFERENCE_SEQUENCE=~{referenceFasta} \
+        INPUT=~{inputBam} \
+        OUTPUT=~{outputPath} \
+        ~{"MINIMUM_MAPPING_QUALITY=" + minimumMappingQuality} \
+        ~{"MINIMUM_BASE_QUALITY=" + minimumBaseQuality} \
+        ~{"COVERAGE_CAP=" + coverageCap}
+    }
+
+    output {
+        File metrics = outputPath
+    }
+
+    runtime {
+        docker: dockerImage
+        time_minutes: timeMinutes
+        memory: memory
+    }
+    
+    parameter_meta {
+        # inputs
+        inputBam: {description: "The input BAM file for which metrics will be collected.", category: "required"}
+        inputBamIndex: {description: "The index of the input BAM file.", category: "required"}
+        referenceFasta: {description: "The reference fasta file which was also used for mapping.", category: "required"}
+        referenceFastaDict: {description: "The sequence dictionary associated with the reference fasta file.",
+                             category: "required"}
+        referenceFastaFai: {description: "The index for the reference fasta file.", category: "required"}
+        outputPath: {description: "The path picard CollectWgsMetrics' output should be written to.", category: "common"}
+        minimumMappingQuality: {description: "Equivalent to picard CollectWgsMetrics' MINIMUM_MAPPING_QUALITY option.", category: "advanced"}
+        minimumBaseQuality: {description: "Equivalent to picard CollectWgsMetrics' MINIMUM_BASE_QUALITY option.", category: "advanced"}
+        coverageCap: {description: "Equivalent to picard CollectWgsMetrics' OVERAGE_CAP option.", category: "advanced"}
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}
+
 task CreateSequenceDictionary {
     input {
         File inputFile
diff --git a/sambamba.wdl b/sambamba.wdl
index df5ab4d1accd5568093587d1ca58bd4287e71bb3..4c2115e07dd95b2d126488a36846338b745b48fd 100644
--- a/sambamba.wdl
+++ b/sambamba.wdl
@@ -20,13 +20,56 @@ version 1.0
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 # SOFTWARE.
 
+task Flagstat {
+    input {
+        File inputBam
+        File inputBamIndex
+        String outputPath = "./flagstat.txt"
+
+        Int threads = 2
+        String memory = "8G"
+        Int timeMinutes = 120
+        String dockerImage = "quay.io/biocontainers/sambamba:0.7.1--h148d290_2"
+    }
+
+    command {
+        sambamba flagstat \
+        -t ~{threads} \
+        ~{inputBam} \
+        > ~{outputPath}
+    }
+
+    output {
+        File stats = outputPath
+    }
+
+    runtime {
+        cpu: threads
+        memory: memory
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        docker: dockerImage
+    }
+
+    parameter_meta {
+        inputBam: {description: "The input BAM file.", category: "required"}
+        inputBamIndex: {description: "The index for the BAM file.", category: "required"}
+        outputPath: {description: "The path to write the ouput to.", category: "required"}
+
+        threads: {description: "The number of threads that will be used for this task.", category: "advanced"}
+        memory: {description: "The amount of memory available to the job.", category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.", category: "advanced"}
+    }
+}
+
+
 task Markdup {
     input {
         Array[File] inputBams
         String outputPath
         Int compressionLevel = 1
         # sortBufferSize and ioBufferSize taken from markdup defaults as of sambamba 0.7.1.
-        Int sortBufferSize = 2048
+        Int sortBufferSize = 4096
         Int ioBufferSize = 128
         Boolean removeDuplicates = false
 
@@ -38,10 +81,10 @@ task Markdup {
         # 2 threads reduces wall clock time by more than 40%.
         Int threads = 2
         # According to the manual sambamba markdup uses the sortbufferSize + 2 times the ioBuffer size.
-        # Added 1024 mb as a margin of safety. Real life use with this setting uses 2.7 GiB.
-        Int memoryMb = 1024 + sortBufferSize + 2 * ioBufferSize
+        # Added 8192 mb as a margin of safety. Real life use with this setting uses 2.7 GiB.
+        Int memoryMb = 8192 + sortBufferSize + 2 * ioBufferSize
         # Time minute calculation does not work well for higher number of threads.
-        Int timeMinutes = 1 + ceil(size(inputBams, "G") * 8) / threads
+        Int timeMinutes = 1 + ceil(size(inputBams, "G") * 25) / threads
         String dockerImage = "quay.io/biocontainers/sambamba:0.7.1--h148d290_2"
     }
 
diff --git a/snpeff.wdl b/snpeff.wdl
new file mode 100644
index 0000000000000000000000000000000000000000..4a3640c7a8b5ea2a9da742bb76f7e1e0e48e38a6
--- /dev/null
+++ b/snpeff.wdl
@@ -0,0 +1,96 @@
+version 1.0
+
+# MIT License
+#
+# Copyright (c) 2020 Leiden University Medical Center
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+task SnpEff {
+    input {
+        File vcf
+        File vcfIndex
+        String genomeVersion
+        File datadirZip
+        String outputPath = "./snpeff.vcf"
+        Boolean hgvs = true
+        Boolean lof = true
+        Boolean noDownstream = false
+        Boolean noIntergenic = false
+        Boolean noShiftHgvs = false
+        Int? upDownStreamLen
+
+        String memory = "9G"
+        String javaXmx = "8G"
+        Int timeMinutes = 60
+        String dockerImage = "quay.io/biocontainers/snpeff:5.0--0"
+    }
+
+    command {
+        set -e
+        mkdir -p "$(dirname ~{outputPath})"
+        unzip ~{datadirZip}
+        snpEff -Xmx~{javaXmx} -XX:ParallelGCThreads=1 \
+        -v \
+        ~{genomeVersion} \
+        -noDownload \
+        -dataDir $PWD/data \
+        ~{vcf} \
+        ~{true="-hgvs" false="-noHgvs" hgvs} \
+        ~{true="-lof" false="-noLof" lof} \
+        ~{true="-no-downstream" false="" noDownstream} \
+        ~{true="-no-intergenic" false="" noIntergenic} \
+        ~{true="-noShiftHgvs" false="" noShiftHgvs} \
+        ~{"-upDownStreamLen " + upDownStreamLen} \
+        > ~{outputPath}
+        rm -r $PWD/data
+    }
+
+    output {
+        File outputVcf = outputPath
+    }
+
+    runtime {
+        docker: dockerImage
+        time_minutes: timeMinutes # !UnknownRuntimeKey
+        memory: memory
+    }
+
+    parameter_meta {
+        vcf: {description: "A VCF file to analyse.", category: "required"}
+        vcfIndex: {description: "The index for the VCF file.", category: "required"}
+        genomeVersion: {description: "The version of the genome to be used. The database for this genome must be present in the datadirZip.", category: "required"}
+        datadirZip: {description: "A zip file containing the directory of databases. This zip file must contain a directory called `data`, with the database mentioned in the genomeVersion input as subdirectory.",
+                     category: "required"}
+        outputPath: {description: "The path to write the output to.", category: "common"}
+        hgvs: {description: "Equivalent to `-hgvs` if true or `-noHgvs` if false.", category: "advanced"}
+        lof: {description: "Equivalent to `-lof` if true or `-noLof` if false.", category: "advanced"}
+        noDownstream: {description: "Equivalent to the `-no-downstream` flag.", category: "advanced"}
+        noIntergenic: {description: "Equivalent to the `-no-intergenic` flag.", category: "advanced"}
+        noShiftHgvs: {description: "Equivalent to the `-noShiftHgvs` flag.", category: "advanced"}
+        upDownStreamLen: {descriptoin: "Equivalent to the `-upDownStreamLen` option.", category: "advanced"}
+
+        memory: {description: "The amount of memory this job will use.", category: "advanced"}
+        javaXmx: {description: "The maximum memory available to the program. Should be lower than `memory` to accommodate JVM overhead.",
+                  category: "advanced"}
+        timeMinutes: {description: "The maximum amount of time the job will run in minutes.", category: "advanced"}
+        dockerImage: {description: "The docker image used for this task. Changing this may result in errors which the developers may choose not to address.",
+                      category: "advanced"}
+    }
+}