diff --git a/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/MultiSampleQScript.scala b/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/MultiSampleQScript.scala
index 6a6039bcd28675e63444a810843bc799941b71bb..86804903c16a0cbda64bf338a902fa6ac2dc5bb1 100644
--- a/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/MultiSampleQScript.scala
+++ b/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/MultiSampleQScript.scala
@@ -194,10 +194,11 @@ trait MultiSampleQScript extends SummaryQScript { qscript: QScript =>
   protected def sampleIds: Set[String] = ConfigUtils.any2map(globalConfig.map("samples")).keySet
 
   protected lazy val nameRegex = """^[a-zA-Z0-9][a-zA-Z0-9-_]+[a-zA-Z0-9]$""".r
-  protected lazy val nameError = " name invalid." +
-    "Name must have at least 3 characters," +
+  protected lazy val nameError = "has an invalid name. " +
+    "Sample names must have at least 3 characters, " +
     "must begin and end with an alphanumeric character, " +
-    "and must not have whitespace."
+    "and must not have whitespace and special characters. " +
+    "Dash (-) and underscore (_) are permitted."
 
   /** Runs addAndTrackJobs method for each sample */
   final def addSamplesJobs() {
diff --git a/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/report/ReportBuilder.scala b/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/report/ReportBuilder.scala
index 2ec92145abe956ec94a11342e49b57752ed7f5fc..2bfbe8f6afdc65b78e1eead4148a375425029575 100644
--- a/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/report/ReportBuilder.scala
+++ b/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/report/ReportBuilder.scala
@@ -93,9 +93,9 @@ trait ReportBuilder extends ToolCommand {
   private var total = 0
 
   private var _sampleId: Option[String] = None
-  protected def sampleId = _sampleId
+  protected[report] def sampleId = _sampleId
   private var _libId: Option[String] = None
-  protected def libId = _libId
+  protected[report] def libId = _libId
 
   case class ExtFile(resourcePath: String, targetPath: String)
 
@@ -152,6 +152,8 @@ trait ReportBuilder extends ToolCommand {
     total = ReportBuilder.countPages(indexPage)
     logger.info(total + " pages to be generated")
 
+    done = 0
+
     logger.info("Generate pages")
     val jobs = generatePage(summary, indexPage, cmdArgs.outputDir,
       args = pageArgs ++ cmdArgs.pageArgs.toMap ++
@@ -216,7 +218,7 @@ object ReportBuilder {
   protected val engine = new TemplateEngine()
 
   /** Cache of temp file for templates from the classpath / jar */
-  private var templateCache: Map[String, File] = Map()
+  private[report] var templateCache: Map[String, File] = Map()
 
   /** This will give the total number of pages including all nested pages */
   def countPages(page: ReportPage): Int = {
diff --git a/public/biopet-core/src/test/resources/empty_summary.json b/public/biopet-core/src/test/resources/empty_summary.json
new file mode 100644
index 0000000000000000000000000000000000000000..13644bf720a111170cc305dca20ae343db22351a
--- /dev/null
+++ b/public/biopet-core/src/test/resources/empty_summary.json
@@ -0,0 +1,11 @@
+{
+  "samples": {
+    "sampleName": {
+      "libraries": {
+        "libName": {
+
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/public/biopet-core/src/test/resources/template.ssp b/public/biopet-core/src/test/resources/template.ssp
new file mode 100644
index 0000000000000000000000000000000000000000..0a10aab03881d7c4c8294a671c683e69ad8705a2
--- /dev/null
+++ b/public/biopet-core/src/test/resources/template.ssp
@@ -0,0 +1,2 @@
+<%@ var arg: String%>
+${arg}
\ No newline at end of file
diff --git a/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/MultiSampleQScriptTest.scala b/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/MultiSampleQScriptTest.scala
index 5bb2948830fba23db63cac137db92f584b81fec0..9bb7bec2657a571c9b98fc08f62d427386c9097c 100644
--- a/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/MultiSampleQScriptTest.scala
+++ b/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/MultiSampleQScriptTest.scala
@@ -4,13 +4,14 @@ import java.io.File
 
 import nl.lumc.sasc.biopet.core.MultiSampleQScript.Gender
 import nl.lumc.sasc.biopet.core.extensions.Md5sum
-import nl.lumc.sasc.biopet.utils.ConfigUtils
+import nl.lumc.sasc.biopet.utils.{ Logging, ConfigUtils }
 import nl.lumc.sasc.biopet.utils.config.Config
 import org.broadinstitute.gatk.queue.QScript
 import org.scalatest.Matchers
 import org.scalatest.testng.TestNGSuite
 import org.testng.annotations.Test
 
+import scala.language.reflectiveCalls
 import scala.collection.mutable.ListBuffer
 
 /**
@@ -90,6 +91,20 @@ class MultiSampleQScriptTest extends TestNGSuite with Matchers {
 
     script.functions.size shouldBe 1
   }
+
+  @Test
+  def testInvalidSampleName: Unit = {
+    val script = MultiSampleQScriptTest(sample4 :: Nil)
+    script.init()
+    script.biopetScript()
+    val msg = script.getLastLogMessage
+    msg shouldBe "Sample 'Something.Invalid' has an invalid name. " +
+      "Sample names must have at least 3 characters, " +
+      "must begin and end with an alphanumeric character, " +
+      "and must not have whitespace and special characters. " +
+      "Dash (-) and underscore (_) are permitted."
+
+  }
 }
 
 object MultiSampleQScriptTest {
@@ -120,6 +135,10 @@ object MultiSampleQScriptTest {
     "lib3" -> Map("test" -> "3-3")
   ))))
 
+  val sample4 = Map("samples" -> Map("Something.Invalid" -> Map("libraries" -> Map(
+    "lib1" -> Map("test" -> "4-1")
+  ))))
+
   val child = Map("samples" -> Map("child" -> Map("tags" -> Map(
     "gender" -> "male", "father" -> "father", "mother" -> "mother"))))
   val father = Map("samples" -> Map("father" -> Map("tags" -> Map("gender" -> "male"))))
@@ -136,6 +155,11 @@ object MultiSampleQScriptTest {
         .foldLeft(Map[String, Any]()) { case (a, b) => ConfigUtils.mergeMaps(a, b) })
 
       val root = null
+
+      def getLastLogMessage: String = {
+        Logging.errors.toList.last.getMessage
+      }
+
       class Sample(id: String) extends AbstractSample(id) {
         class Library(id: String) extends AbstractLibrary(id) {
           /** Function that add library jobs */
diff --git a/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/report/MultisampleReportBuilderTest.scala b/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/report/MultisampleReportBuilderTest.scala
new file mode 100644
index 0000000000000000000000000000000000000000..20fab25d85bf438872e3c09c9c62c45d56b807b9
--- /dev/null
+++ b/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/report/MultisampleReportBuilderTest.scala
@@ -0,0 +1,46 @@
+package nl.lumc.sasc.biopet.core.report
+
+import java.io.File
+import java.nio.file.Paths
+
+import com.google.common.io.Files
+import org.scalatest.Matchers
+import org.scalatest.testng.TestNGSuite
+import org.testng.annotations.Test
+
+/**
+ * Created by pjvanthof on 24/02/16.
+ */
+class MultisampleReportBuilderTest extends TestNGSuite with Matchers {
+  private def resourcePath(p: String): String = {
+    Paths.get(getClass.getResource(p).toURI).toString
+  }
+
+  @Test
+  def testGeneratePages(): Unit = {
+    val builder = new MultisampleReportBuilder {
+      def reportName: String = "test"
+      def indexPage: ReportPage = ReportPage("Samples" -> generateSamplesPage(Map()) :: Nil, Nil, Map())
+
+      def samplePage(sampleId: String, args: Map[String, Any]): ReportPage =
+        ReportPage("Libraries" -> generateLibraryPage(Map("sampleId" -> Some(sampleId))) :: Nil, Nil, Map())
+
+      def libraryPage(sampleId: String, libraryId: String, args: Map[String, Any]) = ReportPage(Nil, Nil, Map())
+    }
+
+    val tempDir = Files.createTempDir()
+    tempDir.deleteOnExit()
+    val args = Array("-s", resourcePath("/empty_summary.json"), "-o", tempDir.getAbsolutePath)
+    builder.main(args)
+    builder.extFiles.foreach(x => new File(tempDir, "ext" + File.separator + x.targetPath) should exist)
+
+    def createFile(path: String*) = new File(tempDir, path.mkString(File.separator))
+
+    createFile("index.html") should exist
+    createFile("Samples", "index.html") should exist
+    createFile("Samples", "sampleName", "index.html") should exist
+    createFile("Samples", "sampleName", "Libraries", "index.html") should exist
+    createFile("Samples", "sampleName", "Libraries", "libName", "index.html") should exist
+  }
+
+}
diff --git a/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/report/ReportBuilderTest.scala b/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/report/ReportBuilderTest.scala
new file mode 100644
index 0000000000000000000000000000000000000000..fd321d65ff8b1625f7b4a4dd25fff3bcf7754105
--- /dev/null
+++ b/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/report/ReportBuilderTest.scala
@@ -0,0 +1,75 @@
+package nl.lumc.sasc.biopet.core.report
+
+import java.io.File
+import java.nio.file.Paths
+
+import com.google.common.io.Files
+import org.scalatest.Matchers
+import org.scalatest.testng.TestNGSuite
+import org.testng.annotations.{ DataProvider, Test }
+
+/**
+ * Created by pjvanthof on 24/02/16.
+ */
+class ReportBuilderTest extends TestNGSuite with Matchers {
+
+  private def resourcePath(p: String): String = {
+    Paths.get(getClass.getResource(p).toURI).toString
+  }
+
+  @DataProvider(name = "testGeneratePages")
+  def generatePageProvider = {
+    val sample = Array(Some("sampleName"), None)
+    val lib = Array(Some("libName"), None)
+    val nested = Array(false, true)
+    for (s <- sample; l <- lib; n <- nested) yield Array(s, l, n)
+  }
+
+  @Test(dataProvider = "testGeneratePages")
+  def testGeneratePages(sample: Option[String], lib: Option[String], nested: Boolean): Unit = {
+    val builder = new ReportBuilder {
+      def reportName: String = "test"
+      def indexPage: ReportPage = ReportPage(
+        (if (nested) "p1" -> ReportPage(Nil, Nil, Map()) :: Nil else Nil), Nil, Map())
+    }
+
+    val tempDir = Files.createTempDir()
+    tempDir.deleteOnExit()
+    val args = Array("-s", resourcePath("/empty_summary.json"), "-o", tempDir.getAbsolutePath) ++
+      sample.map(x => Array("-a", s"sampleId=$x")).getOrElse(Array()) ++
+      lib.map(x => Array("-a", s"libId=$x")).getOrElse(Array())
+    builder.main(args)
+    builder.sampleId shouldBe sample
+    builder.libId shouldBe lib
+    builder.extFiles.foreach(x => new File(tempDir, "ext" + File.separator + x.targetPath) should exist)
+    new File(tempDir, "index.html") should exist
+    new File(tempDir, "p1" + File.separator + "index.html").exists() shouldBe nested
+  }
+
+  @Test
+  def testCountPages: Unit = {
+    ReportBuilder.countPages(ReportPage(Nil, Nil, Map())) shouldBe 1
+    ReportBuilder.countPages(ReportPage(
+      "p1" -> ReportPage(Nil, Nil, Map()) :: Nil,
+      Nil, Map())) shouldBe 2
+    ReportBuilder.countPages(ReportPage(
+      "p1" -> ReportPage(Nil, Nil, Map()) :: "p2" -> ReportPage(Nil, Nil, Map()) :: Nil,
+      Nil, Map())) shouldBe 3
+    ReportBuilder.countPages(ReportPage(
+      "p1" -> ReportPage("p1" -> ReportPage(Nil, Nil, Map()) :: Nil, Nil, Map()) :: Nil,
+      Nil, Map())) shouldBe 3
+    ReportBuilder.countPages(ReportPage(
+      "p1" -> ReportPage(Nil, Nil, Map()) :: "p2" -> ReportPage("p1" -> ReportPage(Nil, Nil, Map()) :: Nil, Nil, Map()) :: Nil,
+      Nil, Map())) shouldBe 4
+  }
+
+  @Test
+  def testRenderTemplate: Unit = {
+    ReportBuilder.templateCache = Map()
+    ReportBuilder.templateCache shouldBe empty
+    ReportBuilder.renderTemplate("/template.ssp", Map("arg" -> "test")) shouldBe "test"
+    ReportBuilder.templateCache.size shouldBe 1
+    ReportBuilder.renderTemplate("/template.ssp", Map("arg" -> "bla")) shouldBe "bla"
+    ReportBuilder.templateCache.size shouldBe 1
+  }
+}
diff --git a/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/report/ReportSectionTest.scala b/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/report/ReportSectionTest.scala
new file mode 100644
index 0000000000000000000000000000000000000000..f6ffd79e59c2d66b07f1b30d4d9c767734a75b1b
--- /dev/null
+++ b/public/biopet-core/src/test/scala/nl/lumc/sasc/biopet/core/report/ReportSectionTest.scala
@@ -0,0 +1,17 @@
+package nl.lumc.sasc.biopet.core.report
+
+import org.scalatest.Matchers
+import org.scalatest.testng.TestNGSuite
+import org.testng.annotations.Test
+
+/**
+ * Created by pjvanthof on 24/02/16.
+ */
+class ReportSectionTest extends TestNGSuite with Matchers {
+
+  @Test
+  def testSectionRender: Unit = {
+    ReportSection("/template.ssp", Map("arg" -> "test")).render() shouldBe "test"
+    ReportSection("/template.ssp").render(Map("arg" -> "test")) shouldBe "test"
+  }
+}
diff --git a/public/biopet-tools-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/tools/GvcfToBed.scala b/public/biopet-tools-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/tools/GvcfToBed.scala
index 3ad955d35f0768dcc1a056c999778cb8c6b2e205..5c7e551b2d3a4be6fdefeed5db3119e71ba20845 100644
--- a/public/biopet-tools-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/tools/GvcfToBed.scala
+++ b/public/biopet-tools-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/tools/GvcfToBed.scala
@@ -25,7 +25,7 @@ class GvcfToBed(val root: Configurable) extends ToolCommandFunction {
   var minQuality: Int = 0
 
   @Argument(doc = "inverse", required = false)
-  var inverse: Boolean = false
+  var inverse: Option[File] = None
 
   override def defaultCoreMemory = 4.0
 
@@ -35,7 +35,7 @@ class GvcfToBed(val root: Configurable) extends ToolCommandFunction {
       required("-O", outputBed) +
       optional("-S", sample) +
       optional("--minGenomeQuality", minQuality) +
-      conditional(inverse, "--inverted")
+      optional("--invertedOutputBed", inverse)
   }
 
 }
diff --git a/public/biopet-tools/src/main/scala/nl/lumc/sasc/biopet/tools/SeqStat.scala b/public/biopet-tools/src/main/scala/nl/lumc/sasc/biopet/tools/SeqStat.scala
index 74d2512b9e09f40430477ab42afd6410f5582514..69b8e7a8a20279a20c6306ecf23901755e82cc12 100644
--- a/public/biopet-tools/src/main/scala/nl/lumc/sasc/biopet/tools/SeqStat.scala
+++ b/public/biopet-tools/src/main/scala/nl/lumc/sasc/biopet/tools/SeqStat.scala
@@ -15,10 +15,10 @@
  */
 package nl.lumc.sasc.biopet.tools
 
-import java.io.{ PrintWriter, File }
+import java.io.{ File, PrintWriter }
 
 import htsjdk.samtools.fastq.{ FastqReader, FastqRecord }
-import nl.lumc.sasc.biopet.utils.{ ToolCommand, ConfigUtils }
+import nl.lumc.sasc.biopet.utils.{ ConfigUtils, ToolCommand }
 
 import scala.collection.JavaConverters._
 import scala.collection.immutable.Map
@@ -26,7 +26,8 @@ import scala.collection.mutable
 import scala.language.postfixOps
 
 /**
- * Created by pjvanthof on 11/09/15.
+ * Created by wyleung on 01/12/14.
+ * Modified by pjvanthof and warindrarto on 27/06/2015
  */
 object SeqStat extends ToolCommand {
 
@@ -41,12 +42,12 @@ object SeqStat extends ToolCommand {
   var nucs: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer()
 
   // generate the baseHistogram and readHistogram
-  var baseHistogram: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer()
-  var readHistogram: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer()
+  var baseQualHistogram: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer()
+  var readQualHistogram: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer()
 
   var nucleotideHistoMap: mutable.Map[Char, Long] = mutable.Map()
   private var baseQualHistoMap: mutable.Map[Int, Long] = mutable.Map(0 -> 0)
-  private var readQualHistoMap: mutable.Map[Int, Long] = mutable.Map(0 -> 0)
+  private var readQualGTEHistoMap: mutable.Map[Int, Long] = mutable.Map(0 -> 0)
 
   case class Args(fastq: File = null, outputJson: Option[File] = None) extends AbstractArgs
 
@@ -83,14 +84,15 @@ object SeqStat extends ToolCommand {
    */
   def detectPhredEncoding(quals: mutable.ArrayBuffer[Long]): Unit = {
     // substract 1 on high value, because we start from index 0
-    val l_qual = quals.takeWhile(_ == 0).length
-    val h_qual = quals.length - 1
+    val qual_low_boundery = quals.takeWhile(_ == 0).length
+    val qual_high_boundery = quals.length - 1
 
-    (l_qual < 59, h_qual > 74) match {
+    (qual_low_boundery < 59, qual_high_boundery > 74) match {
       case (false, true) => phredEncoding = Solexa
-      // TODO: check this later on
-      // complex case, we cannot tell wheter this is a sanger or solexa
-      // but since the h_qual exceeds any Sanger/Illumina1.8 quals, we can `assume` this is solexa
+        // TODO: check this later on
+        // complex case, we cannot tell wheter this is a sanger or solexa
+        // but since the qual_high_boundery exceeds any Sanger/Illumina1.8 quals, we can `assume` this is solexa
+        // New @ 2016/01/26: Illumina X ten samples can contain Phred=Q42 (qual_high_boundery==75/K)
       case (true, true)  => phredEncoding = Solexa
       // this is definite a sanger sequence, the lower end is sanger only
       case (true, false) => phredEncoding = Sanger
@@ -102,16 +104,18 @@ object SeqStat extends ToolCommand {
   // 'nuc' are the nucleotides 'ACTGN', the max ASCII value for this is T, pre-init the ArrayBuffer to this value
   // as we don't expect the have other 'higher' numbered Nucleotides for now.
   case class BaseStat(qual: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer(),
-                      nuc: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer.fill('T'.toInt + 1)(0))
+                      nucs: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer.fill('T'.toInt + 1)(0))
 
   case class ReadStat(qual: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer(),
-                      nuc: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer.fill('T'.toInt + 1)(0),
+                      nucs: mutable.ArrayBuffer[Long] = mutable.ArrayBuffer.fill('T'.toInt + 1)(0),
                       var withN: Long = 0L,
                       lengths: mutable.ArrayBuffer[Int] = mutable.ArrayBuffer())
 
   val baseStats: mutable.ArrayBuffer[BaseStat] = mutable.ArrayBuffer()
   val readStats: ReadStat = new ReadStat()
 
+  var readLengthHistogram: mutable.Map[String, Long] = mutable.Map.empty
+
   /**
    * Compute the quality metric per read
    * Results are stored in baseStats and readStats
@@ -130,25 +134,22 @@ object SeqStat extends ToolCommand {
       readStats.lengths ++= mutable.ArrayBuffer.fill(record.length - readStats.lengths.length + 1)(0)
     }
 
-    val readQual = record.getBaseQualityString
+    val readQuality = record.getBaseQualityString
     val readNucleotides = record.getReadString
 
-    if (record.length >= readStats.lengths.size) // Extends array when length not yet possible
-      (0 to (record.length - readStats.lengths.size)).foreach(_ => readStats.lengths.append(0))
-
     readStats.lengths(record.length) += 1
 
     for (t <- 0 until record.length()) {
-      if (baseStats(t).qual.length <= readQual(t)) {
-        baseStats(t).qual ++= mutable.ArrayBuffer.fill(readQual(t).toInt - baseStats(t).qual.length + 1)(0)
+      if (baseStats(t).qual.length <= readQuality(t)) {
+        baseStats(t).qual ++= mutable.ArrayBuffer.fill(readQuality(t).toInt - baseStats(t).qual.length + 1)(0)
       }
-      baseStats(t).qual(readQual(t)) += 1
-      baseStats(t).nuc(readNucleotides(t)) += 1
-      readStats.nuc(readNucleotides(t)) += 1
+      baseStats(t).qual(readQuality(t)) += 1
+      baseStats(t).nucs(readNucleotides(t)) += 1
+      readStats.nucs(readNucleotides(t)) += 1
     }
 
     // implicit conversion to Int using foldLeft(0)
-    val avgQual: Int = readQual.sum / readQual.length
+    val avgQual: Int = readQuality.sum / readQuality.length
     if (readStats.qual.length <= avgQual) {
       readStats.qual ++= mutable.ArrayBuffer.fill(avgQual - readStats.qual.length + 1)(0)
     }
@@ -179,74 +180,53 @@ object SeqStat extends ToolCommand {
       if (quals.length <= baseStats(pos).qual.length) {
         quals ++= mutable.ArrayBuffer.fill(baseStats(pos).qual.length - quals.length)(0)
       }
-      if (nucs.length <= baseStats(pos).nuc.length) {
-        for (_ <- nucs.length until baseStats(pos).nuc.length) nucs.append(0)
+      if (nucs.length <= baseStats(pos).nucs.length) {
+        nucs ++= mutable.ArrayBuffer.fill( baseStats(pos).nucs.length - nucs.length )(0)
       }
       // count into the quals
       baseStats(pos).qual.zipWithIndex foreach { case (value, index) => quals(index) += value }
       // count N into nucs
-      baseStats(pos).nuc.zipWithIndex foreach { case (value, index) => nucs(index) += value }
+      baseStats(pos).nucs.zipWithIndex foreach { case (value, index) => nucs(index) += value }
     }
     detectPhredEncoding(quals)
     logger.debug("Detected '" + phredEncoding.toString.toLowerCase + "' encoding in fastq file ...")
 
-    for (pos <- nucs.indices) {
-      // always export the N-nucleotide
-      if (nucs(pos) > 0 || pos.toChar == 'N') {
-        nucleotideHistoMap += (pos.toChar -> nucs(pos))
-      }
-    }
+    nucleotideHistoMap = nucs.toList
+      .foldLeft(mutable.Map[Char, Long]())(
+        (output, nucleotideCount) => output + (output.size.toChar -> nucleotideCount)
+      )
+      // ensure bases: `ACTGN` is always reported even having a zero count.
+      // Other chars might be counted also, these are also reported
+      .retain((nucleotide, count) => (count > 0 || "ACTGN".contains(nucleotide.toString)))
 
-    // init baseHistogram with the bounderies of the report values
-    for (pos <- 0 until reportValues.max + 1) {
-      baseHistogram.append(0)
-      readHistogram.append(0)
-    }
+    baseQualHistogram = quals.slice(phredEncoding.id, quals.size)
+    baseQualHistogram ++= mutable.ArrayBuffer.fill(reportValues.max + 1 - baseQualHistogram.size)(0L)
 
-    for (pos <- quals.indices) {
-      val key: Int = pos - phredEncoding.id
-      if (key >= 0) {
-        baseHistogram(key) += quals(pos)
-      }
-    }
+    readQualHistogram = readStats.qual.slice(phredEncoding.id, readStats.qual.size)
+    readQualHistogram ++= mutable.ArrayBuffer.fill(reportValues.max + 1 - readQualHistogram.size)(0L)
 
-    for (pos <- readStats.qual.indices) {
-      val key: Int = pos - phredEncoding.id
-      if (key > 0) {
-        // count till the max of baseHistogram.length
-        for (histokey <- 0 until key + 1) {
-          readHistogram(histokey) += readStats.qual(pos)
+    readQualGTEHistoMap = readQualHistogram.indices
+      .foldLeft(mutable.Map[Int, Long]())(
+        (output, index) => {
+          output + (output.keys.size -> readQualHistogram.slice(index, readQualHistogram.size).sum)
         }
-      }
-    }
-
-    for (pos <- readHistogram.indices) {
-      readQualHistoMap += (pos -> readHistogram(pos))
-    }
+      )
 
   }
 
-  def main(args: Array[String]): Unit = {
-
-    val commandArgs: Args = parseArgs(args)
-
-    logger.info("Start seqstat")
-    seqStat(new FastqReader(commandArgs.fastq))
-    summarize()
-    logger.info("Seqstat done")
-
-    val report: Map[String, Any] = Map(
+  def reportMap(fastqPath: File): Map[String, Any] = {
+    Map(
       ("files",
         Map(
           ("fastq", Map(
-            ("path", commandArgs.fastq))
+            ("path", fastqPath.getAbsolutePath))
           )
         )
       ),
       ("stats", Map(
         ("bases", Map(
           ("num_total", nucleotideHistoMap.values.sum),
-          ("num_qual", baseHistogram.toList),
+          ("num_qual", baseQualHistogram.toList),
           ("nucleotides", nucleotideHistoMap.toMap)
         )),
         ("reads", Map(
@@ -254,11 +234,24 @@ object SeqStat extends ToolCommand {
           ("num_total", readStats.qual.sum),
           ("len_min", readStats.lengths.takeWhile(_ == 0).length),
           ("len_max", readStats.lengths.length - 1),
-          ("num_avg_qual_gte", readQualHistoMap.toMap),
-          ("qual_encoding", phredEncoding.toString.toLowerCase)
+          ("num_avg_qual_gte", readQualGTEHistoMap.toMap),
+          ("qual_encoding", phredEncoding.toString.toLowerCase),
+          ("len_histogram", readStats.lengths.toList)
         ))
       ))
     )
+  }
+
+  def main(args: Array[String]): Unit = {
+
+    val commandArgs: Args = parseArgs(args)
+
+    logger.info("Start seqstat")
+    seqStat(new FastqReader(commandArgs.fastq))
+    summarize()
+    logger.info("Seqstat done")
+
+    val report = reportMap(commandArgs.fastq)
 
     commandArgs.outputJson match {
       case Some(file) => {
diff --git a/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/GvcfToBedTest.scala b/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/GvcfToBedTest.scala
index 5664c9c6fe306a3d845fd1cbe1bf9ded22f153f3..aac4cb6c7e0ddaa0f7e9479110758d95e6cb3ac6 100644
--- a/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/GvcfToBedTest.scala
+++ b/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/GvcfToBedTest.scala
@@ -12,6 +12,8 @@ import org.scalatest.testng.TestNGSuite
 import GvcfToBed._
 import org.testng.annotations.Test
 
+import scala.io.Source
+
 /**
  * Created by ahbbollen on 13-10-15.
  */
@@ -39,4 +41,46 @@ class GvcfToBedTest extends TestNGSuite with Matchers with MockitoSugar {
     VcfUtils.hasMinGenomeQuality(record2, "Sample_102", 3) shouldBe true
     VcfUtils.hasMinGenomeQuality(record2, "Sample_102", 99) shouldBe false
   }
+
+  @Test
+  def testGvcfToBedOutput = {
+    val tmp = File.createTempFile("gvcf2bedtest", ".bed")
+    tmp.deleteOnExit()
+    val args: Array[String] = Array("-I", unvepped.getAbsolutePath, "-O", tmp.getAbsolutePath, "-S", "Sample_101",
+      "--minGenomeQuality", "99")
+    main(args)
+
+    Source.fromFile(tmp).getLines().size shouldBe 0
+
+    val tmp2 = File.createTempFile("gvcf2bedtest", ".bed")
+    tmp2.deleteOnExit()
+    val args2: Array[String] = Array("-I", unvepped.getAbsolutePath, "-O", tmp2.getAbsolutePath, "-S", "Sample_102",
+      "--minGenomeQuality", "2")
+    main(args2)
+
+    Source.fromFile(tmp2).getLines().size shouldBe 1
+  }
+
+  @Test
+  def testGvcfToBedInvertedOutput = {
+    val tmp = File.createTempFile("gvcf2bedtest", ".bed")
+    val tmp_inv = File.createTempFile("gvcf2bedtest", ".bed")
+    tmp.deleteOnExit()
+    tmp_inv.deleteOnExit()
+    val args: Array[String] = Array("-I", unvepped.getAbsolutePath, "-O", tmp.getAbsolutePath, "-S", "Sample_101",
+      "--minGenomeQuality", "99", "--invertedOutputBed", tmp_inv.getAbsolutePath)
+    main(args)
+
+    Source.fromFile(tmp_inv).getLines().size shouldBe 1
+
+    val tmp2 = File.createTempFile("gvcf2bedtest", ".bed")
+    val tmp2_inv = File.createTempFile("gvcf2bedtest", ".bed")
+    tmp2.deleteOnExit()
+    tmp2_inv.deleteOnExit()
+    val args2: Array[String] = Array("-I", unvepped.getAbsolutePath, "-O", tmp.getAbsolutePath, "-S", "Sample_102",
+      "--minGenomeQuality", "3", "--invertedOutputBed", tmp2_inv.getAbsolutePath)
+    main(args2)
+
+    Source.fromFile(tmp2_inv).getLines().size shouldBe 0
+  }
 }
diff --git a/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/SeqStatTest.scala b/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/SeqStatTest.scala
index c9dd5e290c3cd4da97c58198da2a596258ed0c64..b60ef10126a30b4ccabb8d8b8595f44e7a3cd889 100644
--- a/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/SeqStatTest.scala
+++ b/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/SeqStatTest.scala
@@ -88,11 +88,25 @@ class SeqStatTest extends TestNGSuite with MockitoSugar with Matchers {
   def testEncodingBaseHistogram(fqMock: FastqReader) = {
 
     val seqstat = SeqStat
-    baseHistogram(40) shouldEqual 5
-    baseHistogram(39) shouldEqual 5
-    baseHistogram(34) shouldEqual 5
-    baseHistogram(33) shouldEqual 5
-    baseHistogram.head shouldEqual 5
+    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"
+
   }
 
   @Test def testArgsMinimum() = {
diff --git a/public/shiva/src/main/resources/nl/lumc/sasc/biopet/pipelines/shiva/sampleVariants.ssp b/public/shiva/src/main/resources/nl/lumc/sasc/biopet/pipelines/shiva/sampleVariants.ssp
index 674910dabedc3fcb7d7759cd8952d93a68240f01..1d3eef152a5ab0016b4823098d166b41b994df1f 100644
--- a/public/shiva/src/main/resources/nl/lumc/sasc/biopet/pipelines/shiva/sampleVariants.ssp
+++ b/public/shiva/src/main/resources/nl/lumc/sasc/biopet/pipelines/shiva/sampleVariants.ssp
@@ -52,7 +52,7 @@
 #end
 
 #if (showPlot)
-    #{ ShivaReport.variantSummaryPlot(outputDir, "variantSummary", summary, sampleId = sampleId) }#
+    #{ ShivaReport.variantSummaryPlot(outputDir, "variantSummary", summary, sampleId = sampleId, target = target) }#
     <div class="panel-body">
         <img src="variantSummary.png" class="img-responsive" />
     </div>