Skip to content
Snippets Groups Projects
Commit f4893563 authored by bow's avatar bow
Browse files

Remove all explicit null use in ExtractAlignedFastq

parent 1f5b341b
No related branches found
No related tags found
No related merge requests found
......@@ -19,7 +19,7 @@ import nl.lumc.sasc.biopet.core.ToolCommand
object ExtractAlignedFastq extends ToolCommand {
type FastqPair = (FastqRecord, FastqRecord)
type FastqInput = (FastqRecord, Option[FastqRecord])
/**
* Function to create iterator over Interval given input interval string
......@@ -74,7 +74,7 @@ object ExtractAlignedFastq extends ToolCommand {
def makeMembershipFunction(iv: Iterator[Interval],
inAln: File,
minMapQ: Int = 0,
commonSuffixLength: Int = 0): (FastqPair => Boolean) = {
commonSuffixLength: Int = 0): (FastqInput => Boolean) = {
val inAlnReader = SamReaderFactory
.make()
......@@ -112,47 +112,32 @@ object ExtractAlignedFastq extends ToolCommand {
}
)
(pair: FastqPair) => pair._2 match {
case null => selected.contains(pair._1.getReadHeader)
case otherwise =>
(pair: FastqInput) => pair._2 match {
case None => selected.contains(pair._1.getReadHeader)
case Some(x) =>
require(commonSuffixLength < pair._1.getReadHeader.length)
require(commonSuffixLength < pair._2.getReadHeader.length)
require(commonSuffixLength < x.getReadHeader.length)
selected.contains(pair._1.getReadHeader.dropRight(commonSuffixLength))
}
}
def selectFastqReads(memFunc: FastqPair => Boolean,
inputFastq1: FastqReader,
outputFastq1: BasicFastqWriter,
inputFastq2: Option[FastqReader] = None,
outputFastq2: Option[BasicFastqWriter] = None): Unit = {
val i1 = inputFastq1.iterator.asScala
val i2 = inputFastq2 match {
case Some(x) => x.iterator.asScala
case None => Iterator.continually(null)
}
val o1 = outputFastq1
val o2 = (inputFastq2, outputFastq2) match {
case (None, None) => null
case (_, None) => throw new IllegalArgumentException("Missing output FASTQ 2")
case (None, _) => throw new IllegalArgumentException("Output FASTQ 2 supplied but there is no input FASTQ 2")
case (Some(_), Some(x)) => x
}
logger.info("Writing output file(s) ...")
// zip, filter based on function, and write to output file(s)
i1.zip(i2)
def extractReads(memFunc: FastqInput => Boolean,
inputFastq1: FastqReader, outputFastq1: BasicFastqWriter): Unit =
inputFastq1.iterator.asScala
.zip(Iterator.continually(None))
.filter(rec => memFunc(rec._1, rec._2))
.foreach {
case (rec1, null) =>
o1.write(rec1)
case (rec1, rec2) =>
o1.write(rec1)
o2.write(rec2)
}
}
.foreach(rec => outputFastq1.write(rec._1))
def extractReads(memFunc: FastqInput => Boolean,
inputFastq1: FastqReader, outputFastq1: BasicFastqWriter,
inputFastq2:FastqReader, outputFastq2: BasicFastqWriter): Unit =
inputFastq1.iterator.asScala
.zip(inputFastq2.iterator.asScala)
.filter(rec => memFunc(rec._1, Some(rec._2)))
.foreach(rec => {
outputFastq1.write(rec._1)
outputFastq2.write(rec._2)
})
case class Args(inputBam: File = new File(""),
intervals: List[String] = List.empty[String],
......@@ -239,10 +224,19 @@ object ExtractAlignedFastq extends ToolCommand {
minMapQ = commandArgs.minMapQ,
commonSuffixLength = commandArgs.commonSuffixLength)
selectFastqReads(memFunc,
inputFastq1 = new FastqReader(commandArgs.inputFastq1),
inputFastq2 = commandArgs.inputFastq2.map(x => new FastqReader(x)),
outputFastq1 = new BasicFastqWriter(commandArgs.outputFastq1),
outputFastq2 = commandArgs.outputFastq2.map(x => new BasicFastqWriter(x)))
(commandArgs.inputFastq2, commandArgs.outputFastq2) match {
case (None, None) => extractReads(memFunc,
new FastqReader(commandArgs.inputFastq1),
new BasicFastqWriter(commandArgs.inputFastq1))
case (Some(i2), Some(o2)) => extractReads(memFunc,
new FastqReader(commandArgs.inputFastq1),
new BasicFastqWriter(commandArgs.outputFastq1),
new FastqReader(i2),
new BasicFastqWriter(o2))
case _ => // handled by the command line config check above
}
}
}
......@@ -33,11 +33,11 @@ class ExtractAlignedFastqUnitTest extends TestNGSuite with MockitoSugar with Mat
private def makeRecord(header: String): FastqRecord =
new FastqRecord(header, "ATGC", "", "HIHI")
private def makeSingleRecords(headers: String*): Map[String, FastqPair] =
headers.map(x => (x, (makeRecord(x), null))).toMap
private def makeSingleRecords(headers: String*): Map[String, FastqInput] =
headers.map(x => (x, (makeRecord(x), None))).toMap
private def makePairRecords(headers: (String, (String, String))*): Map[String, FastqPair] =
headers.map(x => (x._1, (makeRecord(x._2._1), makeRecord(x._2._2)))).toMap
private def makePairRecords(headers: (String, (String, String))*): Map[String, FastqInput] =
headers.map(x => (x._1, (makeRecord(x._2._1), Some(makeRecord(x._2._2))))).toMap
private def makeClue(tName: String, f: File, rName: String): String =
tName + " on " + f.getName + ", read " + rName + ": "
......@@ -112,7 +112,7 @@ class ExtractAlignedFastqUnitTest extends TestNGSuite with MockitoSugar with Mat
@Test(dataProvider = "singleAlnProvider1")
def testSingleBamDefault(name: String, feat: Interval, inAln: File,
fastqMap: Map[String, FastqPair], resultMap: Map[String, Boolean]) = {
fastqMap: Map[String, FastqInput], resultMap: Map[String, Boolean]) = {
require(resultMap.keySet == fastqMap.keySet)
val memFunc = makeMembershipFunction(Iterator(feat), inAln)
for ((key, (rec1, rec2)) <- fastqMap) {
......@@ -140,7 +140,7 @@ class ExtractAlignedFastqUnitTest extends TestNGSuite with MockitoSugar with Mat
@Test(dataProvider = "singleAlnProvider2")
def testSingleBamMinMapQ(name: String, feat: Interval, inAln: File, minMapQ: Int,
fastqMap: Map[String, FastqPair], resultMap: Map[String, Boolean]) = {
fastqMap: Map[String, FastqInput], resultMap: Map[String, Boolean]) = {
require(resultMap.keySet == fastqMap.keySet)
val memFunc = makeMembershipFunction(Iterator(feat), inAln, minMapQ)
for ((key, (rec1, rec2)) <- fastqMap) {
......@@ -178,7 +178,7 @@ class ExtractAlignedFastqUnitTest extends TestNGSuite with MockitoSugar with Mat
@Test(dataProvider = "pairAlnProvider1")
def testPairBamDefault(name: String, feat: Interval, inAln: File,
fastqMap: Map[String, FastqPair], resultMap: Map[String, Boolean]) = {
fastqMap: Map[String, FastqInput], resultMap: Map[String, Boolean]) = {
require(resultMap.keySet == fastqMap.keySet)
val memFunc = makeMembershipFunction(Iterator(feat), inAln, commonSuffixLength = 2)
for ((key, (rec1, rec2)) <- fastqMap) {
......@@ -189,53 +189,28 @@ class ExtractAlignedFastqUnitTest extends TestNGSuite with MockitoSugar with Mat
}
@Test def testWriteSingleBamDefault() = {
val memFunc = (recs: FastqPair) => Set("r01", "r03").contains(recs._1.getReadHeader)
val memFunc = (recs: FastqInput) => Set("r01", "r03").contains(recs._1.getReadHeader)
val in1 = new FastqReader(resourceFile("/single01.fq"))
val mo1 = mock[BasicFastqWriter]
selectFastqReads(memFunc, in1, mo1)
extractReads(memFunc, in1, mo1)
verify(mo1, times(2)).write(anyObject.asInstanceOf[FastqRecord])
verify(mo1).write(new FastqRecord("r01", "A", "", "H"))
verify(mo1).write(new FastqRecord("r03", "G", "", "H"))
}
@Test def testWritePairBamDefault() = {
val memFunc = (recs: FastqPair) => Set("r01/1", "r01/2", "r03/1", "r03/2").contains(recs._1.getReadHeader)
val memFunc = (recs: FastqInput) => Set("r01/1", "r01/2", "r03/1", "r03/2").contains(recs._1.getReadHeader)
val in1 = new FastqReader(resourceFile("/paired01a.fq"))
val in2 = Some(new FastqReader(resourceFile("/paired01b.fq")))
val in2 = new FastqReader(resourceFile("/paired01b.fq"))
val mo1 = mock[BasicFastqWriter]
val mo2 = Some(mock[BasicFastqWriter])
selectFastqReads(memFunc, in1, mo1, in2, mo2)
val mo2 = mock[BasicFastqWriter]
extractReads(memFunc, in1, mo1, in2, mo2)
verify(mo1, times(2)).write(anyObject.asInstanceOf[FastqRecord])
verify(mo1).write(new FastqRecord("r01/1", "A", "", "H"))
verify(mo1).write(new FastqRecord("r03/1", "G", "", "H"))
verify(mo2.get, times(2)).write(anyObject.asInstanceOf[FastqRecord])
verify(mo2.get).write(new FastqRecord("r01/2", "T", "", "I"))
verify(mo2.get).write(new FastqRecord("r03/2", "C", "", "I"))
}
@Test def testWriteNoOutputFastq2() = {
val memFunc: (FastqPair => Boolean) = (recs) => true
val in1 = mock[FastqReader]
val in2 = Some(mock[FastqReader])
val out1 = mock[BasicFastqWriter]
val thrown = intercept[IllegalArgumentException] {
selectFastqReads(memFunc, in1, out1, in2)
}
thrown.getMessage should ===("Missing output FASTQ 2")
verify(out1, never).write(anyObject.asInstanceOf[FastqRecord])
}
@Test def testWriteNoInputFastq2() = {
val memFunc: (FastqPair => Boolean) = (recs) => true
val in1 = mock[FastqReader]
val out1 = mock[BasicFastqWriter]
val out2 = Some(mock[BasicFastqWriter])
val thrown = intercept[IllegalArgumentException] {
selectFastqReads(memFunc, in1, out1, outputFastq2 = out2)
}
thrown.getMessage should ===("Output FASTQ 2 supplied but there is no input FASTQ 2")
verify(out1, never).write(anyObject.asInstanceOf[FastqRecord])
verify(out2.get, never).write(anyObject.asInstanceOf[FastqRecord])
verify(mo2, times(2)).write(anyObject.asInstanceOf[FastqRecord])
verify(mo2).write(new FastqRecord("r01/2", "T", "", "I"))
verify(mo2).write(new FastqRecord("r03/2", "C", "", "I"))
}
@Test def testMainMinimum() = {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment