Commit e1fecc16 authored by Wai Yi Leung's avatar Wai Yi Leung
Browse files

Merge branch 'feature-sv_unit_tests' into 'develop'

Feature sv unit tests

This is some basic unit testing for sv calling

@wyleung can merge this and then add pindel on that other branch to this?

See merge request !323
parents 2e177fd8 30e7d8ce
package nl.lumc.sasc.biopet.tools
import java.io.{OutputStream, PrintStream, ByteArrayOutputStream}
import java.io.{ OutputStream, PrintStream, ByteArrayOutputStream }
import java.nio.file.Paths
import htsjdk.samtools.fastq.FastqRecord
import nl.lumc.sasc.biopet.utils.Logging
import org.apache.log4j.{FileAppender, Appender}
import org.apache.log4j.{ FileAppender, Appender }
import org.scalatest.Matchers
import org.scalatest.testng.TestNGSuite
import org.testng.annotations.{DataProvider, Test}
import org.testng.annotations.{ DataProvider, Test }
import scala.collection.JavaConversions._
/**
* Created by pjvan_thof on 2/17/16.
*/
* Created by pjvan_thof on 2/17/16.
*/
class ValidateFastqTest extends TestNGSuite with Matchers {
@Test
......@@ -38,17 +38,17 @@ class ValidateFastqTest extends TestNGSuite with Matchers {
@DataProvider(name = "providerGetPossibleEncodings")
def providerGetPossibleEncodings = Array(
Array(None, None, Nil),
Array(Some('A'), None, Nil),
Array(None, Some('A'), Nil),
Array(Some('E'), Some('E'), List("Sanger", "Solexa", "Illumina 1.3+", "Illumina 1.5+", "Illumina 1.8+")),
Array(Some('+'), Some('+'), List("Sanger", "Illumina 1.8+")),
Array(Some('!'), Some('I'), List("Sanger", "Illumina 1.8+")),
Array(Some('!'), Some('J'), List("Illumina 1.8+")),
Array(Some(';'), Some('h'), List("Solexa")),
Array(Some('@'), Some('h'), List("Solexa", "Illumina 1.3+")),
Array(Some('C'), Some('h'), List("Solexa", "Illumina 1.3+", "Illumina 1.5+"))
)
Array(None, None, Nil),
Array(Some('A'), None, Nil),
Array(None, Some('A'), Nil),
Array(Some('E'), Some('E'), List("Sanger", "Solexa", "Illumina 1.3+", "Illumina 1.5+", "Illumina 1.8+")),
Array(Some('+'), Some('+'), List("Sanger", "Illumina 1.8+")),
Array(Some('!'), Some('I'), List("Sanger", "Illumina 1.8+")),
Array(Some('!'), Some('J'), List("Illumina 1.8+")),
Array(Some(';'), Some('h'), List("Solexa")),
Array(Some('@'), Some('h'), List("Solexa", "Illumina 1.3+")),
Array(Some('C'), Some('h'), List("Solexa", "Illumina 1.3+", "Illumina 1.5+"))
)
@Test(dataProvider = "providerGetPossibleEncodings")
def testGetPossibleEncodings(min: Option[Char], max: Option[Char], output: List[String]): Unit = {
......
......@@ -33,7 +33,7 @@ class ShivaSvCalling(val root: Configurable) extends QScript with SummaryQScript
def this() = this(null)
@Input(doc = "Bam files (should be deduped bams)", shortName = "BAM", required = true)
protected var inputBamsArg: List[File] = Nil
protected[shiva] var inputBamsArg: List[File] = Nil
var inputBams: Map[String, File] = Map()
......@@ -58,6 +58,7 @@ class ShivaSvCalling(val root: Configurable) extends QScript with SummaryQScript
require(callers.nonEmpty, "must select at least 1 SV caller, choices are: " + callersList.map(_.name).mkString(", "))
callers.foreach { caller =>
caller.inputBams = inputBams
caller.outputDir = new File(outputDir, caller.name)
add(caller)
}
......
......@@ -54,6 +54,8 @@ class Delly(val root: Configurable) extends SvCaller {
add(delly)
}
require(catVariants.inputFiles.nonEmpty, "Must atleast 1 SV-type be selected for Delly")
add(catVariants)
}
}
......
/**
* Biopet is built on top of GATK Queue for building bioinformatic
* pipelines. It is mainly intended to support LUMC SHARK cluster which is running
* SGE. But other types of HPC that are supported by GATK Queue (such as PBS)
* should also be able to execute Biopet tools and pipelines.
*
* Copyright 2014 Sequencing Analysis Support Core - Leiden University Medical Center
*
* Contact us at: sasc@lumc.nl
*
* A dual licensing mode is applied. The source code within this project that are
* not part of GATK Queue is freely available for non-commercial use under an AGPL
* license; For commercial users or users who do not want to follow the AGPL
* license, please contact us to obtain a separate license.
*/
package nl.lumc.sasc.biopet.pipelines.shiva
import java.io.{ File, FileOutputStream }
import java.nio.file.Paths
import com.google.common.io.Files
import nl.lumc.sasc.biopet.extensions.breakdancer.{ BreakdancerVCF, BreakdancerConfig, BreakdancerCaller }
import nl.lumc.sasc.biopet.extensions.clever.CleverCaller
import nl.lumc.sasc.biopet.extensions.delly.DellyCaller
import nl.lumc.sasc.biopet.utils.config.Config
import nl.lumc.sasc.biopet.extensions.Freebayes
import nl.lumc.sasc.biopet.extensions.gatk.CombineVariants
import nl.lumc.sasc.biopet.extensions.tools.VcfFilter
import nl.lumc.sasc.biopet.utils.ConfigUtils
import org.apache.commons.io.FileUtils
import org.broadinstitute.gatk.queue.QSettings
import org.scalatest.Matchers
import org.scalatest.testng.TestNGSuite
import org.testng.annotations.{ AfterClass, DataProvider, Test }
import scala.collection.mutable.ListBuffer
/**
* Test class for [[ShivaVariantcalling]]
*
* Created by pjvan_thof on 3/2/15.
*/
class ShivaSvCallingTest extends TestNGSuite with Matchers {
def initPipeline(map: Map[String, Any]): ShivaSvCalling = {
new ShivaSvCalling {
override def configName = "shivasvcalling"
override def globalConfig = new Config(ConfigUtils.mergeMaps(map, ShivaSvCallingTest.config))
qSettings = new QSettings
qSettings.runName = "test"
}
}
@DataProvider(name = "shivaSvCallingOptions")
def shivaSvCallingOptions = {
val bool = Array(true, false)
(for (
bams <- 0 to 3;
delly <- bool;
clever <- bool;
breakdancer <- bool
) yield Array(bams, delly, clever, breakdancer)).toArray
}
@Test(dataProvider = "shivaSvCallingOptions")
def testShivaSvCalling(bams: Int,
delly: Boolean,
clever: Boolean,
breakdancer: Boolean) = {
val callers: ListBuffer[String] = ListBuffer()
if (delly) callers.append("delly")
if (clever) callers.append("clever")
if (breakdancer) callers.append("breakdancer")
val map = Map("sv_callers" -> callers.toList)
val pipeline = initPipeline(map)
pipeline.inputBams = (for (n <- 1 to bams) yield n.toString -> ShivaSvCallingTest.inputTouch("bam_" + n + ".bam")).toMap
val illegalArgumentException = pipeline.inputBams.isEmpty || (!delly && !clever && !breakdancer)
if (illegalArgumentException) intercept[IllegalArgumentException] {
pipeline.init()
pipeline.script()
}
if (!illegalArgumentException) {
pipeline.init()
pipeline.script()
val summaryCallers = pipeline.summarySettings("sv_callers")
if (delly) assert(summaryCallers.contains("delly"))
else assert(!summaryCallers.contains("delly"))
if (clever) assert(summaryCallers.contains("clever"))
else assert(!summaryCallers.contains("clever"))
if (breakdancer) assert(summaryCallers.contains("breakdancer"))
else assert(!summaryCallers.contains("breakdancer"))
pipeline.functions.count(_.isInstanceOf[BreakdancerCaller]) shouldBe (if (breakdancer) bams else 0)
pipeline.functions.count(_.isInstanceOf[BreakdancerConfig]) shouldBe (if (breakdancer) bams else 0)
pipeline.functions.count(_.isInstanceOf[BreakdancerVCF]) shouldBe (if (breakdancer) bams else 0)
pipeline.functions.count(_.isInstanceOf[CleverCaller]) shouldBe (if (clever) bams else 0)
pipeline.functions.count(_.isInstanceOf[DellyCaller]) shouldBe (if (delly) (bams * 4) else 0)
}
}
@DataProvider(name = "dellyOptions")
def dellyOptions = {
val bool = Array(true, false)
(for (
del <- bool;
dup <- bool;
inv <- bool;
tra <- bool
) yield Array(1, del, dup, inv, tra)).toArray
}
@Test(dataProvider = "dellyOptions")
def testShivaDelly(bams: Int, del: Boolean, dup: Boolean, inv: Boolean, tra: Boolean): Unit = {
val map = Map("sv_callers" -> List("delly"), "delly" ->
Map("DEL" -> del, "DUP" -> dup, "INV" -> inv, "TRA" -> tra)
)
val pipeline = initPipeline(map)
pipeline.inputBams = Map("bam" -> ShivaVariantcallingTest.inputTouch("bam" + ".bam"))
if (!del && !dup && !inv && !tra) intercept[IllegalArgumentException] {
pipeline.init()
pipeline.script()
}
else {
pipeline.init()
pipeline.script()
pipeline.functions.count(_.isInstanceOf[DellyCaller]) shouldBe
((if (del) 1 else 0) + (if (dup) 1 else 0) + (if (inv) 1 else 0) + (if (tra) 1 else 0))
}
}
@Test
def testWrongCaller(): Unit = {
val map = Map("sv_callers" -> List("this is not a caller"))
val pipeline = initPipeline(map)
pipeline.inputBams = Map("bam" -> ShivaVariantcallingTest.inputTouch("bam" + ".bam"))
intercept[IllegalArgumentException] {
pipeline.init()
pipeline.script()
}
}
private def resourcePath(p: String): String = {
Paths.get(getClass.getResource(p).toURI).toString
}
@Test
def testInputBamsArg(): Unit = {
val pipeline = initPipeline(Map())
pipeline.inputBamsArg :+= new File(resourcePath("/paired01.bam"))
pipeline.init()
pipeline.script()
val summaryCallers = pipeline.summarySettings("sv_callers")
assert(summaryCallers.contains("delly"))
assert(summaryCallers.contains("clever"))
assert(summaryCallers.contains("breakdancer"))
}
@AfterClass def removeTempOutputDir() = {
FileUtils.deleteDirectory(ShivaSvCallingTest.outputDir)
}
}
object ShivaSvCallingTest {
val outputDir = Files.createTempDir()
new File(outputDir, "input").mkdirs()
def inputTouch(name: String): File = {
val file = new File(outputDir, "input" + File.separator + name).getAbsoluteFile
Files.touch(file)
file
}
private def copyFile(name: String): Unit = {
val is = getClass.getResourceAsStream("/" + name)
val os = new FileOutputStream(new File(outputDir, name))
org.apache.commons.io.IOUtils.copy(is, os)
os.close()
}
copyFile("ref.fa")
copyFile("ref.dict")
copyFile("ref.fa.fai")
val config = Map(
"name_prefix" -> "test",
"output_dir" -> outputDir,
"cache" -> true,
"dir" -> "test",
"vep_script" -> "test",
"reference_fasta" -> (outputDir + File.separator + "ref.fa"),
"gatk_jar" -> "test",
"samtools" -> Map("exe" -> "test"),
"md5sum" -> Map("exe" -> "test"),
"bgzip" -> Map("exe" -> "test"),
"tabix" -> Map("exe" -> "test"),
"breakdancerconfig" -> Map("exe" -> "test"),
"breakdancercaller" -> Map("exe" -> "test"),
"clever" -> Map("exe" -> "test"),
"delly" -> Map("exe" -> "test"),
"varscan_jar" -> "test"
)
}
\ No newline at end of file
......@@ -80,10 +80,12 @@ class ShivaVariantcallingTest extends TestNGSuite with Matchers {
val illegalArgumentException = pipeline.inputBams.isEmpty || (!raw && !bcftools && !bcftoolsSinglesample && !freebayes && !varscanCnsSinglesample)
if (illegalArgumentException) intercept[IllegalArgumentException] {
pipeline.init()
pipeline.script()
}
if (!illegalArgumentException) {
pipeline.init()
pipeline.script()
pipeline.functions.count(_.isInstanceOf[CombineVariants]) shouldBe (1 + (if (raw) 1 else 0) + (if (varscanCnsSinglesample) 1 else 0))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment