SeqStatTest.scala 5.03 KB
Newer Older
1
/**
bow's avatar
bow committed
2
3
4
5
6
7
8
9
10
11
12
13
14
 * 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.
15
16
17
18
19
20
 */
package nl.lumc.sasc.biopet.tools

import java.io.File
import java.nio.file.Paths

Wai Yi Leung's avatar
Wai Yi Leung committed
21
22
import htsjdk.samtools.fastq.{FastqReader, FastqRecord}
import org.mockito.Mockito.{inOrder => inOrd, when}
23
24
25
import org.scalatest.Matchers
import org.scalatest.mock.MockitoSugar
import org.scalatest.testng.TestNGSuite
Wai Yi Leung's avatar
Wai Yi Leung committed
26
import org.testng.annotations.{DataProvider, Test}
27
28
29

import scala.collection.JavaConverters._

bow's avatar
bow committed
30
class SeqStatTest extends TestNGSuite with MockitoSugar with Matchers {
31

Wai Yi Leung's avatar
Wai Yi Leung committed
32
  import nl.lumc.sasc.biopet.tools.FqEncoding._
Peter van 't Hof's avatar
Peter van 't Hof committed
33
  import nl.lumc.sasc.biopet.tools.SeqStat._
34
35
36
37
38
39
40
41
42
43

  private def resourceFile(p: String): File =
    new File(resourcePath(p))

  private def resourcePath(p: String): String =
    Paths.get(getClass.getResource(p).toURI).toString

  // Helper functions to create iterator over FastqRecords given its IDs as Ints
  // Record with 'A' and Qual==39 (SangerEncoding)
  private def recordsOver(ids: String*): java.util.Iterator[FastqRecord] = ids
Wai Yi Leung's avatar
Wai Yi Leung committed
44
    .map(x => new FastqRecord(x, "ACGTN", "", "HIBC!"))
45
46
47
48
49
50
51
52
    .toIterator.asJava

  @DataProvider(name = "mockReaderProvider")
  def mockReaderProvider() =
    Array(
      Array(mock[FastqReader])
    )

Wai Yi Leung's avatar
Wai Yi Leung committed
53
  @Test(dataProvider = "mockReaderProvider", groups = Array("sanger"), singleThreaded = true)
54
55
  def testDefault(fqMock: FastqReader) = {
    when(fqMock.iterator) thenReturn recordsOver("1", "2", "3")
56
57
  }

Wai Yi Leung's avatar
Wai Yi Leung committed
58
  @Test(dataProvider = "mockReaderProvider", groups = Array("read"), singleThreaded = true)
59
60
  def testSeqCountReads(fqMock: FastqReader) = {
    when(fqMock.iterator) thenReturn recordsOver("1", "2", "3", "4", "5")
61

bow's avatar
bow committed
62
    val seqstat = SeqStat
Wai Yi Leung's avatar
Wai Yi Leung committed
63
    val numReads = seqstat.seqStat(fqMock)
64
65
66
    numReads shouldBe 5
  }

Wai Yi Leung's avatar
Wai Yi Leung committed
67
  @Test(dataProvider = "mockReaderProvider", groups = Array("phredscore"), singleThreaded = true, dependsOnGroups = Array("read"))
68
  def testEncodingDetectionSanger(fqMock: FastqReader) = {
69

bow's avatar
bow committed
70
    val seqstat = SeqStat
Wai Yi Leung's avatar
Wai Yi Leung committed
71
    seqstat.summarize()
72

Wai Yi Leung's avatar
Wai Yi Leung committed
73
    seqstat.phredEncoding shouldBe Sanger
Wai Yi Leung's avatar
Wai Yi Leung committed
74
75
76
77
78
  }

  @Test(dataProvider = "mockReaderProvider", groups = Array("nucleocount"), singleThreaded = true, dependsOnGroups = Array("phredscore"))
  def testEncodingNucleotideCount(fqMock: FastqReader) = {

bow's avatar
bow committed
79
    val seqstat = SeqStat
Wai Yi Leung's avatar
Wai Yi Leung committed
80
81
82
83
84
    nucleotideHistoMap('N') shouldEqual 5
    nucleotideHistoMap('A') shouldEqual 5
    nucleotideHistoMap('C') shouldEqual 5
    nucleotideHistoMap('T') shouldEqual 5
    nucleotideHistoMap('G') shouldEqual 5
Wai Yi Leung's avatar
Wai Yi Leung committed
85
86
87
88
89
  }

  @Test(dataProvider = "mockReaderProvider", groups = Array("basehistogram"), singleThreaded = true, dependsOnGroups = Array("nucleocount"))
  def testEncodingBaseHistogram(fqMock: FastqReader) = {

bow's avatar
bow committed
90
    val seqstat = SeqStat
Wai Yi Leung's avatar
Wai Yi Leung committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    baseQualHistogram(40) shouldEqual 5
    baseQualHistogram(39) shouldEqual 5
    baseQualHistogram(34) shouldEqual 5
    baseQualHistogram(33) shouldEqual 5
    baseQualHistogram.head shouldEqual 5
  }

  @Test(dataProvider = "mockReaderProvider", groups = Array("report"), singleThreaded = true, dependsOnGroups = Array("basehistogram"))
  def testReportOutputScheme(fqMock: FastqReader) = {
    when(fqMock.getFile) thenReturn new File("/tmp/test.fq")
    when(fqMock.iterator) thenReturn recordsOver("1", "2", "3", "4", "5")
    val seqstat = SeqStat
    seqstat.seqStat(fqMock)
    seqstat.summarize()

    val report = seqstat.reportMap(fqMock.getFile)
    report should contain key "files"
    report should contain key "stats"

110
111
  }

Wai Yi Leung's avatar
Wai Yi Leung committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  @Test(dataProvider = "mockReaderProvider", groups = Array("check_readstats"), singleThreaded = true, dependsOnGroups = Array("report"))
  def testReadStatsObject(fqMock: FastqReader) = {
    when(fqMock.getFile) thenReturn new File("/tmp/test.fq")
    when(fqMock.iterator) thenReturn recordsOver("1", "2", "3", "4", "5")
    val seqstat = SeqStat

    // the histogram should store the lenght==0 value also, for example sequence length 5 is size 6.
    // please note that we already loaded the dataset twice in seqstat. (seqstat.Seqstat is called 2 times in previous steps)
    seqstat.readStats.lengths(5) shouldBe 10
    seqstat.readStats.lengths.length shouldBe 6

    seqstat.readStats.nucs.sum shouldBe 50
    seqstat.readStats.withN shouldBe 10
  }

127
128
129
130
131
132
  @Test def testArgsMinimum() = {
    val args = Array(
      "-i", resourcePath("/paired01a.fq"))
    val parsed = parseArgs(args)
    parsed.fastq shouldBe resourceFile("/paired01a.fq")
  }
Sander Bollen's avatar
Sander Bollen committed
133
134

  // TODO: Shared state here. Calling main changes the state, which causes other tests to fail
135
}