diff --git a/biopet-aggregate/pom.xml b/biopet-aggregate/pom.xml
index d105b1ef54883992abee5b83277df325c62a0686..ca3283801777ad853c1f690cdadd9557cc296602 100644
--- a/biopet-aggregate/pom.xml
+++ b/biopet-aggregate/pom.xml
@@ -28,6 +28,7 @@
         <module>../public/bam2wig</module>
         <module>../public/carp</module>
         <module>../public/toucan</module>
+        <module>../public/gwas-test</module>
         <module>../public/shiva</module>
         <module>../public/basty</module>
         <module>../public/tinycap</module>
diff --git a/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/BiopetCommandLineFunction.scala b/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/BiopetCommandLineFunction.scala
index 344f88b89e902bad748628d8e591b79c2daec5d1..f367abc4c5c864215277872818ff306fb4c93a14 100644
--- a/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/BiopetCommandLineFunction.scala
+++ b/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/BiopetCommandLineFunction.scala
@@ -50,9 +50,16 @@ trait BiopetCommandLineFunction extends CommandLineResources { biopetFunction =>
     writer.println("set -eubf")
     writer.println("set -o pipefail")
     lines.foreach(writer.println)
+    jobDelayTime.foreach(x => writer.println(s"sleep $x"))
     writer.close()
   }
 
+  /**
+   *  This value is used to let you job wait a x number of second after it finish.
+   *  This is ionly used when having storage delay issues
+   */
+  var jobDelayTime: Option[Int] = config("job_delay_time")
+
   // This overrides the default "sh" from queue. For Biopet the default is "bash"
   updateJobRun = {
     case jt: JobTemplate =>
@@ -174,6 +181,27 @@ trait BiopetCommandLineFunction extends CommandLineResources { biopetFunction =>
     this
   }
 
+  /**
+   * This method can handle args that have multiple args for 1 arg name
+   * @param argName Name of the arg like "-h" or "--help"
+   * @param values Values for this arg
+   * @param groupSize Values must come in groups of x number, default is 1
+   * @param minGroups Minimal groups that are required, default is 0, when 0 the method return en empty string
+   * @param maxGroups Max number of groups that can be filled here
+   * @return Command part of this arg
+   */
+  def multiArg(argName: String, values: Iterable[Any], groupSize: Int = 1, minGroups: Int = 0, maxGroups: Int = 0): String = {
+    if (values.size % groupSize != 0)
+      Logging.addError(s"Arg '${argName}' values: '${values}' does not fit to a groupSize of ${groupSize}")
+    val groups = values.size / groupSize
+    if (groups < minGroups)
+      Logging.addError(s"Args '${argName}' need atleast $minGroups with size $groupSize")
+    if (maxGroups > 0 && groups > maxGroups)
+      Logging.addError(s"Args '${argName}' may only have $maxGroups with size $groupSize")
+    if (values.nonEmpty) required(argName) + values.map(required(_)).mkString
+    else ""
+  }
+
   @Output(required = false)
   private[core] var stdoutFile: Option[File] = None
 
diff --git a/public/biopet-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/Snptest.scala b/public/biopet-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/Snptest.scala
new file mode 100644
index 0000000000000000000000000000000000000000..d11cfceb9e8b8aaeda7351897f6b58e5e634137c
--- /dev/null
+++ b/public/biopet-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/Snptest.scala
@@ -0,0 +1,172 @@
+package nl.lumc.sasc.biopet.extensions
+
+import java.io.File
+
+import nl.lumc.sasc.biopet.core.{ Version, Reference, BiopetCommandLineFunction }
+import nl.lumc.sasc.biopet.utils.config.Configurable
+import org.broadinstitute.gatk.utils.commandline.{ Output, Input }
+
+import scala.util.matching.Regex
+
+/**
+ * Created by pjvan_thof on 3/25/16.
+ */
+class Snptest(val root: Configurable) extends BiopetCommandLineFunction with Reference with Version {
+  @Input(required = true)
+  var inputGenotypes: List[File] = Nil
+
+  @Input(required = true)
+  var inputSampleFiles: List[File] = Nil
+
+  @Output(required = false)
+  var logFile: Option[File] = None
+
+  @Output(required = false)
+  var outputFile: Option[File] = None
+
+  @Output(required = false)
+  var outputDatabaseFile: Option[File] = None
+
+  var assumeChromosome: Option[String] = config("assume_chromosome")
+  var genotypeField: Option[String] = config("genotype_field")
+  var genotypeProbabilityScale: Option[String] = config("genotype_probability_scale")
+  var haploidGenotypeCoding: Option[String] = config("haploid_genotype_coding")
+  var missingCode: Option[String] = config("missing_code")
+  var totalProbLimit: Option[Double] = config("total_prob_limit")
+  var tableName: Option[String] = config("table_name")
+  var useLongColumnNamingScheme: Boolean = config("use_long_column_naming_scheme", default = false)
+
+  var excludeSamples: List[String] = config("exclude_samples", default = Nil)
+
+  @Input(required = false)
+  val excludeSnp: Option[File] = config("exclude_snp")
+
+  var missThresh: Option[Double] = config("miss_thresh")
+  var baselinePhenotype: Option[String] = config("baseline_phenotype")
+  var bayesian: List[String] = config("bayesian", default = Nil)
+  var callThresh: Option[Double] = config("call_thresh")
+  var frequentist: List[String] = config("frequentist", default = Nil)
+  var fullParameterEstimates: Boolean = config("full_parameter_estimates", default = false)
+  var method: Option[String] = config("method")
+  var pheno: Option[String] = config("pheno")
+  var summaryStatsOnly: Boolean = config("summary_stats_only", default = false)
+
+  var covAll: Boolean = config("cov_all", default = false)
+  var covAllContinuous: Boolean = config("cov_all_continuous", default = false)
+  var covAllDiscrete: Boolean = config("cov_all_discrete", default = false)
+  var covNames: List[String] = config("cov_names", default = Nil)
+  var sexColumn: Option[String] = config("sex_column")
+  var stratifyOn: Option[String] = config("stratify_on")
+
+  var conditionOn: List[String] = config("condition_on", default = Nil)
+
+  var priorAdd: List[String] = config("prior_add", default = Nil)
+  var priorCov: List[String] = config("prior_cov", default = Nil)
+  var priorDom: List[String] = config("prior_dom", default = Nil)
+  var priorGen: List[String] = config("prior_gen", default = Nil)
+  var priorHet: List[String] = config("prior_het", default = Nil)
+  var priorRec: List[String] = config("prior_rec", default = Nil)
+  var tDf: Option[String] = config("t_df")
+  var tPrior: Boolean = config("t_prior", default = false)
+
+  var priorMqtQ: Option[String] = config("prior_mqt_Q")
+  var priorQtVb: Option[String] = config("prior_qt_V_b")
+  var priorQtVq: Option[String] = config("prior_qt_V_q")
+  var priorQtA: Option[String] = config("prior_qt_a")
+  var priorQtB: Option[String] = config("prior_qt_b")
+  var priorQtMeanB: Option[String] = config("prior_qt_mean_b")
+  var priorQtMeanQ: Option[String] = config("prior_qt_mean_q")
+
+  var meanBf: List[String] = config("mean_bf", default = Nil)
+
+  var analysisDescription: Option[String] = config("analysis_description")
+  var chunk: Option[Int] = config("chunk")
+  var debug: Boolean = config("debug", default = false)
+  var hwe: Boolean = config("hwe", default = false)
+  var lowerSampleLimit: Option[Int] = config("lower_sample_limit")
+  var overlap: Boolean = config("overlap", default = false)
+  var printids: Boolean = config("printids", default = false)
+  var quantileNormalisePhenotypes: Boolean = config("quantile_normalise_phenotypes", default = false)
+  var range: List[String] = config("range", default = Nil)
+  var renorm: Boolean = config("renorm", default = false)
+  var snpid: List[String] = config("snpid", default = Nil)
+  var useRawCovariates: Boolean = config("use_raw_covariates", default = false)
+  var useRawPhenotypes: Boolean = config("use_raw_phenotypes", default = false)
+  var noClobber: Boolean = config("no_clobber", default = false)
+
+  executable = config("exe", default = "snptest")
+
+  def versionCommand: String = executable + " -help"
+  def versionRegex: Regex = "Welcome to SNPTEST (.*)".r
+
+  override def beforeGraph(): Unit = {
+    super.beforeGraph()
+    require(inputGenotypes.length == inputSampleFiles.length)
+  }
+
+  def cmdLine: String = {
+    val data = inputGenotypes.zip(inputSampleFiles).flatMap(x => List(x._1, x._2))
+    required(executable) +
+      optional("-assume_chromosome", assumeChromosome) +
+      multiArg("-data", data, groupSize = 2) +
+      optional("-genotype_field", genotypeField) +
+      optional("-genotype_probability_scale", genotypeProbabilityScale) +
+      optional("-haploid_genotype_coding", haploidGenotypeCoding) +
+      optional("-missing_code", missingCode) +
+      optional("-total_prob_limit", totalProbLimit) +
+      optional("-log", logFile) +
+      optional("-o", outputFile) +
+      optional("-odb", outputDatabaseFile) +
+      optional("-table_name", tableName) +
+      conditional(useLongColumnNamingScheme, "-use_long_column_naming_scheme") +
+      multiArg("-exclude_samples", excludeSamples) +
+      optional("-exclude_snp", excludeSnp) +
+      optional("-miss_thresh", missThresh) +
+      optional("-baseline_phenotype", baselinePhenotype) +
+      multiArg("-bayesian", bayesian) +
+      optional("-call_thresh", callThresh) +
+      multiArg("-frequentist", frequentist) +
+      conditional(fullParameterEstimates, "-full_parameter_estimates") +
+      optional("-method", method) +
+      optional("-pheno", pheno) +
+      conditional(summaryStatsOnly, "-summary_stats_only") +
+      conditional(covAll, "-cov_all") +
+      conditional(covAllContinuous, "-cov_all_continuous") +
+      conditional(covAllDiscrete, "-cov_all_discrete") +
+      multiArg("-cov_names", covNames) +
+      optional("-sex_column", sexColumn) +
+      optional("-stratify_on", stratifyOn) +
+      multiArg("-condition_on", conditionOn) +
+      multiArg("-prior_add", priorAdd, groupSize = 4, maxGroups = 1) +
+      multiArg("-prior_cov", priorCov, groupSize = 2, maxGroups = 1) +
+      multiArg("-prior_dom", priorDom, groupSize = 4, maxGroups = 1) +
+      multiArg("-prior_gen", priorGen, groupSize = 6, maxGroups = 1) +
+      multiArg("-prior_het", priorHet, groupSize = 4, maxGroups = 1) +
+      multiArg("-prior_rec", priorRec, groupSize = 4, maxGroups = 1) +
+      optional("-t_df", tDf) +
+      conditional(tPrior, "-t_prior") +
+      optional("-prior_mqt_Q", priorMqtQ) +
+      optional("-prior_qt_V_b", priorQtVb) +
+      optional("-prior_qt_V_q", priorQtVq) +
+      optional("-prior_qt_a", priorQtA) +
+      optional("-prior_qt_b", priorQtB) +
+      optional("-prior_qt_mean_b", priorQtMeanB) +
+      optional("-prior_qt_mean_q", priorQtMeanQ) +
+      multiArg("-mean_bf", meanBf, groupSize = 2, maxGroups = 1) +
+      optional("-analysis_description", analysisDescription) +
+      optional("-analysis_name", analysisName) +
+      optional("-chunk", chunk) +
+      conditional(debug, "-debug") +
+      conditional(hwe, "-hwe") +
+      optional("-lower_sample_limit", lowerSampleLimit) +
+      conditional(overlap, "-overlap") +
+      conditional(printids, "-printids") +
+      conditional(quantileNormalisePhenotypes, "quantile_normalise_phenotypes") +
+      multiArg("-range", range, groupSize = 2) +
+      conditional(renorm, "-renorm") +
+      multiArg("-snpid", snpid) +
+      conditional(useRawCovariates, "-use_raw_covariates") +
+      conditional(useRawPhenotypes, "-use_raw_phenotypes") +
+      conditional(noClobber, "-no_clobber")
+  }
+}
diff --git a/public/biopet-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/gatk/CatVariants.scala b/public/biopet-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/gatk/CatVariants.scala
index d5e3fffcfaeb7d842743ecc9e8896e7de860bbed..ceceed5f64ba51a75b098e4cd1b18beaa4f1894d 100644
--- a/public/biopet-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/gatk/CatVariants.scala
+++ b/public/biopet-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/gatk/CatVariants.scala
@@ -23,7 +23,7 @@ import org.broadinstitute.gatk.utils.commandline.{ Input, Output }
 
 class CatVariants(val root: Configurable) extends BiopetJavaCommandLineFunction with Reference {
 
-  javaMainClass = classOf[org.broadinstitute.gatk.tools.CatVariants].getClass.getName
+  javaMainClass = classOf[org.broadinstitute.gatk.tools.CatVariants].getName
 
   @Input(required = true)
   var inputFiles: List[File] = Nil
@@ -34,6 +34,8 @@ class CatVariants(val root: Configurable) extends BiopetJavaCommandLineFunction
   @Input
   var reference: File = null
 
+  var assumeSorted = false
+
   override def beforeGraph(): Unit = {
     super.beforeGraph()
     if (reference == null) reference = referenceFasta()
@@ -42,7 +44,8 @@ class CatVariants(val root: Configurable) extends BiopetJavaCommandLineFunction
   override def cmdLine = super.cmdLine +
     repeat("-V", inputFiles) +
     required("-out", outputFile) +
-    required("-R", reference)
+    required("-R", reference) +
+    conditional(assumeSorted, "--assumeSorted")
 }
 
 object CatVariants {
diff --git a/public/biopet-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/gatk/SelectVariants.scala b/public/biopet-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/gatk/SelectVariants.scala
new file mode 100644
index 0000000000000000000000000000000000000000..65abc60985a05edcd07aee8646f5b0c04ca839ed
--- /dev/null
+++ b/public/biopet-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/gatk/SelectVariants.scala
@@ -0,0 +1,62 @@
+/**
+ * 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.extensions.gatk
+
+import java.io.File
+
+import nl.lumc.sasc.biopet.utils.config.Configurable
+import org.broadinstitute.gatk.utils.commandline.{ Input, Output }
+
+/**
+ * Extension for CombineVariants from GATK
+ *
+ * Created by pjvan_thof on 2/26/15.
+ */
+class SelectVariants(val root: Configurable) extends Gatk {
+  val analysisType = "SelectVariants"
+
+  @Input(doc = "", required = true)
+  var inputFiles: List[File] = Nil
+
+  @Output(doc = "", required = true)
+  var outputFile: File = null
+
+  var excludeNonVariants: Boolean = false
+
+  var inputMap: Map[File, String] = Map()
+
+  def addInput(file: File, name: String): Unit = {
+    inputFiles :+= file
+    inputMap += file -> name
+  }
+
+  override def beforeGraph(): Unit = {
+    super.beforeGraph()
+    if (outputFile.getName.endsWith(".vcf.gz")) outputFiles :+= new File(outputFile.getAbsolutePath + ".tbi")
+    deps :::= inputFiles.filter(_.getName.endsWith("vcf.gz")).map(x => new File(x.getAbsolutePath + ".tbi"))
+    deps = deps.distinct
+  }
+
+  override def cmdLine = super.cmdLine +
+    (for (file <- inputFiles) yield {
+      inputMap.get(file) match {
+        case Some(name) => required("-V:" + name, file)
+        case _          => required("-V", file)
+      }
+    }).mkString +
+    required("-o", outputFile) +
+    conditional(excludeNonVariants, "--excludeNonVariants")
+}
diff --git a/public/biopet-public-package/pom.xml b/public/biopet-public-package/pom.xml
index 23f18d9b40a5d323fc8c4a387359d383436007ae..2272ea90129dd466c9eeaf09dad4a244b2a97965 100644
--- a/public/biopet-public-package/pom.xml
+++ b/public/biopet-public-package/pom.xml
@@ -74,16 +74,14 @@
             <artifactId>Sage</artifactId>
             <version>${project.version}</version>
         </dependency>
-        <!--
         <dependency>
             <groupId>nl.lumc.sasc</groupId>
-            <artifactId>Yamsvp</artifactId>
+            <artifactId>Kopisu</artifactId>
             <version>${project.version}</version>
         </dependency>
-        -->
         <dependency>
             <groupId>nl.lumc.sasc</groupId>
-            <artifactId>Kopisu</artifactId>
+            <artifactId>GwasTest</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
diff --git a/public/biopet-public-package/src/main/scala/nl/lumc/sasc/biopet/BiopetExecutablePublic.scala b/public/biopet-public-package/src/main/scala/nl/lumc/sasc/biopet/BiopetExecutablePublic.scala
index a6553001fb63493fda08ab069cba37e1e8a2ebe5..8b21fd806b6ed32cf81d02f7adce43bad41e2562 100644
--- a/public/biopet-public-package/src/main/scala/nl/lumc/sasc/biopet/BiopetExecutablePublic.scala
+++ b/public/biopet-public-package/src/main/scala/nl/lumc/sasc/biopet/BiopetExecutablePublic.scala
@@ -32,7 +32,8 @@ object BiopetExecutablePublic extends BiopetExecutable {
     nl.lumc.sasc.biopet.pipelines.toucan.Toucan,
     nl.lumc.sasc.biopet.pipelines.shiva.ShivaSvCalling,
     nl.lumc.sasc.biopet.pipelines.gears.GearsSingle,
-    nl.lumc.sasc.biopet.pipelines.gears.Gears
+    nl.lumc.sasc.biopet.pipelines.gears.Gears,
+    nl.lumc.sasc.biopet.pipelines.gwastest.GwasTest
   )
 
   def pipelines: List[MainCommand] = List(
diff --git a/public/biopet-tools-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/tools/GensToVcf.scala b/public/biopet-tools-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/tools/GensToVcf.scala
new file mode 100644
index 0000000000000000000000000000000000000000..10e5eca751baceeb659e3f602efa0fdc5093b9d0
--- /dev/null
+++ b/public/biopet-tools-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/tools/GensToVcf.scala
@@ -0,0 +1,74 @@
+/**
+ * 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.extensions.tools
+
+import java.io.File
+
+import nl.lumc.sasc.biopet.core.{ Reference, ToolCommandFunction }
+import nl.lumc.sasc.biopet.utils.Logging
+import nl.lumc.sasc.biopet.utils.config.Configurable
+import org.broadinstitute.gatk.utils.commandline.{ Output, Input }
+
+/**
+ *
+ */
+class GensToVcf(val root: Configurable) extends ToolCommandFunction with Reference {
+  def toolObject = nl.lumc.sasc.biopet.tools.GensToVcf
+
+  @Input(doc = "Input genotypes file", required = true)
+  var inputGens: File = _
+
+  @Input(doc = "input Info file", required = false)
+  var inputInfo: Option[File] = None
+
+  @Input(required = true)
+  var samplesFile: File = _
+
+  @Input(required = true)
+  var reference: File = _
+
+  @Output(required = true)
+  var outputVcf: File = _
+
+  var contig: String = _
+
+  var sortInput: Boolean = false
+
+  override def defaultCoreMemory = 6.0
+
+  override def beforeGraph(): Unit = {
+    super.beforeGraph()
+    if (reference == null) reference = referenceFasta()
+    if (contig == null) throw new IllegalStateException("Contig is missing")
+    if (outputVcf.getName.endsWith(".vcf.gz")) outputFiles :+= new File(outputVcf.getAbsolutePath + ".tbi")
+  }
+
+  override def setupRetry(): Unit = {
+    super.setupRetry()
+    sortInput = true
+  }
+
+  override def cmdLine = super.cmdLine +
+    required("--inputGenotypes", inputGens) +
+    required("--inputInfo", inputInfo) +
+    required("--outputVcf", outputVcf) +
+    optional("--contig", contig) +
+    required("--referenceFasta", reference) +
+    required("--samplesFile", samplesFile) +
+    conditional(sortInput, "--sortInput")
+
+}
+
diff --git a/public/biopet-tools-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/tools/SnptestToVcf.scala b/public/biopet-tools-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/tools/SnptestToVcf.scala
new file mode 100644
index 0000000000000000000000000000000000000000..e2f938872d070abcd14f889d562efa27da345e4f
--- /dev/null
+++ b/public/biopet-tools-extensions/src/main/scala/nl/lumc/sasc/biopet/extensions/tools/SnptestToVcf.scala
@@ -0,0 +1,56 @@
+/**
+ * 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.extensions.tools
+
+import java.io.File
+
+import nl.lumc.sasc.biopet.core.{ Reference, ToolCommandFunction }
+import nl.lumc.sasc.biopet.utils.Logging
+import nl.lumc.sasc.biopet.utils.config.Configurable
+import org.broadinstitute.gatk.utils.commandline.{ Input, Output }
+
+/**
+ *
+ */
+class SnptestToVcf(val root: Configurable) extends ToolCommandFunction with Reference {
+  def toolObject = nl.lumc.sasc.biopet.tools.SnptestToVcf
+
+  @Input(doc = "input Info file", required = true)
+  var inputInfo: File = null
+
+  @Input(required = true)
+  var reference: File = _
+
+  @Output(required = true)
+  var outputVcf: File = _
+
+  var contig: String = _
+
+  override def beforeGraph(): Unit = {
+    super.beforeGraph()
+    if (reference == null) reference = referenceFasta()
+    if (contig == null) throw new IllegalStateException("Contig is missing")
+    //if (outputVcf.getName.endsWith(".vcf.gz")) outputFiles :+= new File(outputVcf.getAbsolutePath + ".tbi")
+  }
+
+  override def cmdLine = super.cmdLine +
+    required("--inputInfo", inputInfo) +
+    required("--outputVcf", outputVcf) +
+    optional("--contig", contig) +
+    required("--referenceFasta", reference)
+
+}
+
diff --git a/public/biopet-tools/src/main/scala/nl/lumc/sasc/biopet/tools/GensToVcf.scala b/public/biopet-tools/src/main/scala/nl/lumc/sasc/biopet/tools/GensToVcf.scala
new file mode 100644
index 0000000000000000000000000000000000000000..96b5212ab06be4c0c1243f8d80015093c68c93f1
--- /dev/null
+++ b/public/biopet-tools/src/main/scala/nl/lumc/sasc/biopet/tools/GensToVcf.scala
@@ -0,0 +1,166 @@
+package nl.lumc.sasc.biopet.tools
+
+import java.io.File
+import java.util
+
+import htsjdk.samtools.reference.{ FastaSequenceFile, ReferenceSequenceFileFactory }
+import htsjdk.variant.variantcontext.writer.{ AsyncVariantContextWriter, VariantContextWriterBuilder }
+import htsjdk.variant.variantcontext.{ Allele, GenotypeBuilder, VariantContextBuilder }
+import htsjdk.variant.vcf._
+import nl.lumc.sasc.biopet.utils.ToolCommand
+
+import scala.collection.JavaConversions._
+import scala.io.Source
+
+/**
+ * Created by pjvanthof on 15/03/16.
+ */
+object GensToVcf extends ToolCommand {
+
+  case class Args(inputGenotypes: File = null,
+                  inputInfo: Option[File] = None,
+                  outputVcf: File = null,
+                  sampleFile: File = null,
+                  referenceFasta: File = null,
+                  contig: String = null,
+                  sortInput: Boolean = false) extends AbstractArgs
+
+  class OptParser extends AbstractOptParser {
+    opt[File]('g', "inputGenotypes") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
+      c.copy(inputGenotypes = x)
+    } text "Input genotypes"
+    opt[File]('i', "inputInfo") maxOccurs 1 valueName "<file>" action { (x, c) =>
+      c.copy(inputInfo = Some(x))
+    } text "Input info fields"
+    opt[File]('o', "outputVcf") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
+      c.copy(outputVcf = x)
+    } text "Output vcf file"
+    opt[File]('s', "samplesFile") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
+      c.copy(sampleFile = x)
+    } text "Samples file"
+    opt[File]('R', "referenceFasta") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
+      c.copy(referenceFasta = x)
+    } text "reference fasta file"
+    opt[String]('c', "contig") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
+      c.copy(contig = x)
+    } text "contig of impute file"
+    opt[Unit]("sortInput") maxOccurs 1 action { (x, c) =>
+      c.copy(sortInput = true)
+    } text "In memory sorting"
+  }
+
+  def main(args: Array[String]): Unit = {
+    logger.info("Start")
+
+    val argsParser = new OptParser
+    val cmdArgs = argsParser.parse(args, Args()).getOrElse(throw new IllegalArgumentException)
+
+    val samples = Source.fromFile(cmdArgs.sampleFile).getLines().toArray.drop(2).map(_.split("\t").take(2).mkString("_"))
+
+    val infoIt = cmdArgs.inputInfo.map(Source.fromFile(_).getLines())
+    val infoHeaderKeys = infoIt.map(_.next().split(" ").filterNot(x => x == "rs_id" || x == "position"))
+    val infoHeaderMap = infoHeaderKeys.map(_.zipWithIndex.toMap)
+
+    val metaLines = new util.HashSet[VCFHeaderLine]()
+    for (keys <- infoHeaderKeys; key <- keys)
+      metaLines.add(new VCFInfoHeaderLine(s"GENS_$key", 1, VCFHeaderLineType.String, ""))
+
+    metaLines.add(new VCFFormatHeaderLine("GT", 1, VCFHeaderLineType.String, ""))
+    metaLines.add(new VCFFormatHeaderLine("GP", VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.Float, ""))
+
+    val reference = new FastaSequenceFile(cmdArgs.referenceFasta, true)
+    require(reference.getSequenceDictionary.getSequence(cmdArgs.contig) != null,
+      s"contig '${cmdArgs.contig}' not found on reference")
+
+    val header = new VCFHeader(metaLines, samples.toList)
+    header.setSequenceDictionary(reference.getSequenceDictionary)
+    val writer = new AsyncVariantContextWriter(new VariantContextWriterBuilder()
+      .setOutputFile(cmdArgs.outputVcf)
+      .setReferenceDictionary(header.getSequenceDictionary)
+      .build)
+    writer.writeHeader(header)
+
+    val genotypeIt = Source.fromFile(cmdArgs.inputGenotypes).getLines()
+
+    lazy val fastaFile = ReferenceSequenceFileFactory.getReferenceSequenceFile(cmdArgs.referenceFasta, true, true)
+
+    case class Line(genotype: String, info: Option[String])
+    val lineIt: Iterator[Line] = {
+      val it = infoIt match {
+        case Some(x) => genotypeIt.zip(x).map(x => Line(x._1, Some(x._2)))
+        case _       => genotypeIt.map(x => Line(x, None))
+      }
+
+      if (cmdArgs.sortInput) {
+        logger.info("Start Sorting input files")
+        val list = it.toList
+        val pos = list.map { line =>
+          val values = line.genotype.split(" ")
+          val p = values(2).toInt
+          val alt = values(4)
+          if (alt == "-") p - 1
+          else p
+        }
+        list.zip(pos).sortBy(_._2).map(_._1).toIterator
+      } else it
+    }
+
+    logger.info("Start processing genotypes")
+    var count = 0L
+    for (line <- lineIt) {
+      val genotypeValues = line.genotype.split(" ")
+      val infoValues = line.info.map(_.split(" "))
+
+      val (start, end, ref, alt) = {
+        val start = genotypeValues(2).toInt
+        if (genotypeValues(4) == "-") {
+          val seq = fastaFile.getSubsequenceAt(cmdArgs.contig, start - 1, start + genotypeValues(4).length - 1)
+          (start - 1, start + genotypeValues(4).length - 1,
+            Allele.create(new String(seq.getBases), true), Allele.create(new String(Array(seq.getBases.head))))
+        } else {
+          val ref = Allele.create(genotypeValues(3), true)
+          (start, ref.length - 1 + start, Allele.create(genotypeValues(3), true), Allele.create(genotypeValues(4)))
+        }
+      }
+      val genotypes = samples.toList.zipWithIndex.map {
+        case (sampleName, index) =>
+          val gps = Array(
+            genotypeValues(5 + (index * 3)),
+            genotypeValues(5 + (index * 3) + 1),
+            genotypeValues(5 + (index * 3) + 2)
+          ).map(_.toDouble)
+          val alleles = gps.indexOf(gps.max) match {
+            case 0 => List(ref, ref)
+            case 1 => List(ref, alt)
+            case 2 => List(alt, alt)
+          }
+          new GenotypeBuilder()
+            .name(sampleName)
+            .alleles(alleles)
+            .attribute("GP", gps)
+            .make()
+      }
+
+      val infoMap = infoHeaderKeys.map(_.map(x => ("GENS_" + x) -> infoValues.get(infoHeaderMap.get(x))).toMap).getOrElse(Map())
+
+      val builder = (new VariantContextBuilder)
+        .chr(cmdArgs.contig)
+        .alleles(List(ref, alt))
+        .attributes(infoMap)
+        .start(start)
+        .stop(end)
+        .genotypes(genotypes)
+      val id = genotypeValues(1)
+      if (id.startsWith(cmdArgs.contig + ":")) writer.add(builder.make())
+      else writer.add(builder.id(id).make())
+      count += 1
+      if (count % 10000 == 0) logger.info(s"$count lines processed")
+    }
+
+    logger.info(s"$count lines processed")
+
+    writer.close()
+
+    logger.info("Done")
+  }
+}
diff --git a/public/biopet-tools/src/main/scala/nl/lumc/sasc/biopet/tools/SnptestToVcf.scala b/public/biopet-tools/src/main/scala/nl/lumc/sasc/biopet/tools/SnptestToVcf.scala
new file mode 100644
index 0000000000000000000000000000000000000000..dc18f8770dce76c1f8193486f94b64934e098b26
--- /dev/null
+++ b/public/biopet-tools/src/main/scala/nl/lumc/sasc/biopet/tools/SnptestToVcf.scala
@@ -0,0 +1,126 @@
+package nl.lumc.sasc.biopet.tools
+
+import java.io.File
+import java.util
+
+import htsjdk.samtools.reference.FastaSequenceFile
+import htsjdk.variant.variantcontext.writer.{ AsyncVariantContextWriter, Options, VariantContextWriterBuilder }
+import htsjdk.variant.variantcontext.{ Allele, VariantContextBuilder }
+import htsjdk.variant.vcf._
+import nl.lumc.sasc.biopet.utils.ToolCommand
+
+import scala.collection.JavaConversions._
+import scala.io.Source
+
+/**
+ * Created by pjvanthof on 15/03/16.
+ */
+object SnptestToVcf extends ToolCommand {
+
+  case class Args(inputInfo: File = null,
+                  outputVcf: File = null,
+                  referenceFasta: File = null,
+                  contig: String = null) extends AbstractArgs
+
+  class OptParser extends AbstractOptParser {
+    opt[File]('i', "inputInfo") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
+      c.copy(inputInfo = x)
+    } text "Input info fields"
+    opt[File]('o', "outputVcf") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
+      c.copy(outputVcf = x)
+    } text "Output vcf file"
+    opt[File]('R', "referenceFasta") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
+      c.copy(referenceFasta = x)
+    } text "reference fasta file"
+    opt[String]('c', "contig") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
+      c.copy(contig = x)
+    } text "contig of impute file"
+  }
+
+  def main(args: Array[String]): Unit = {
+    logger.info("Start")
+
+    val argsParser = new OptParser
+    val cmdArgs = argsParser.parse(args, Args()).getOrElse(throw new IllegalArgumentException)
+
+    val infoIt = Source.fromFile(cmdArgs.inputInfo).getLines()
+    val infoHeader = infoIt.find(!_.startsWith("#"))
+
+    infoHeader match {
+      case Some(header) => parseLines(header, infoIt, cmdArgs)
+      case _ =>
+        writeEmptyVcf(cmdArgs.outputVcf, cmdArgs.referenceFasta)
+        logger.info("No header and records found in file")
+    }
+
+    logger.info("Done")
+  }
+
+  def writeEmptyVcf(outputVcf: File, referenceFasta: File): Unit = {
+    val reference = new FastaSequenceFile(referenceFasta, true)
+    val vcfHeader = new VCFHeader()
+    vcfHeader.setSequenceDictionary(reference.getSequenceDictionary)
+    val writer = new VariantContextWriterBuilder()
+      .setOutputFile(outputVcf)
+      .setReferenceDictionary(vcfHeader.getSequenceDictionary)
+      .unsetOption(Options.INDEX_ON_THE_FLY)
+      .build
+    writer.writeHeader(vcfHeader)
+    writer.close()
+  }
+
+  def parseLines(header: String, lineIt: Iterator[String], cmdArgs: Args): Unit = {
+    val headerKeys = header.split(" ")
+    val headerMap = headerKeys.zipWithIndex.toMap
+    require(headerKeys.size == headerMap.size, "Duplicates header keys found")
+    val metaLines = new util.HashSet[VCFHeaderLine]()
+    for (
+      key <- headerKeys if key != "rsid" if key != "chromosome" if key != "position" if key != "alleleA" if key != "alleleB" if key != "alleleA"
+    ) metaLines.add(new VCFInfoHeaderLine(s"ST_$key", 1, VCFHeaderLineType.String, ""))
+
+    val reference = new FastaSequenceFile(cmdArgs.referenceFasta, true)
+    require(reference.getSequenceDictionary.getSequence(cmdArgs.contig) != null,
+      s"contig '${cmdArgs.contig}' not found on reference")
+
+    val vcfHeader = new VCFHeader(metaLines)
+    vcfHeader.setSequenceDictionary(reference.getSequenceDictionary)
+    val writer = new AsyncVariantContextWriter(new VariantContextWriterBuilder()
+      .setOutputFile(cmdArgs.outputVcf)
+      .setReferenceDictionary(vcfHeader.getSequenceDictionary)
+      .unsetOption(Options.INDEX_ON_THE_FLY)
+      .build)
+    writer.writeHeader(vcfHeader)
+
+    val infoKeys = for (
+      key <- headerKeys if key != "rsid" if key != "chromosome" if key != "position" if key != "alleleA" if key != "alleleB" if key != "alleleA"
+    ) yield key
+
+    var counter = 0
+    for (line <- lineIt if !line.startsWith("#")) {
+      val values = line.split(" ")
+      require(values.size == headerKeys.size, "Number of values are not the same as number of header keys")
+      val alleles = List(Allele.create(values(headerMap("alleleA")), true), Allele.create(values(headerMap("alleleB"))))
+      val start = values(headerMap("position")).toLong
+      val end = alleles.head.length() + start - 1
+      val rsid = values(headerMap("rsid"))
+      val builder = (new VariantContextBuilder)
+        .chr(cmdArgs.contig)
+        .alleles(alleles)
+        .start(start)
+        .stop(end)
+        .noGenotypes()
+
+      val infoBuilder = infoKeys.foldLeft(builder) { case (a, b) => a.attribute("ST_" + b, values(headerMap(b)).replaceAll(";", ",")) }
+
+      writer.add(infoBuilder.id(rsid.replaceAll(";", ",")).make())
+
+      counter += 1
+      if (counter % 10000 == 0) logger.info(s"$counter lines processed")
+    }
+
+    logger.info(s"$counter lines processed")
+
+    writer.close()
+
+  }
+}
diff --git a/public/biopet-tools/src/test/resources/gens.samples b/public/biopet-tools/src/test/resources/gens.samples
new file mode 100644
index 0000000000000000000000000000000000000000..1789a409e45a4b78fd83d84808c60e5ba9a494f7
--- /dev/null
+++ b/public/biopet-tools/src/test/resources/gens.samples
@@ -0,0 +1,5 @@
+ID_1	ID_2	missing	hip	knee	hand	knee_or_hip	sex	age	bmi
+0 0 0 D D D D D P P
+sample-1	fam-1	0.0	2	NA	2	2	1	59.0767123287671	27.1314117909924
+sample-2	fam-1	0.0	2	NA	NA	2	2	48.4958904109589	23.8754325259516
+sample-3	fam-1	0.0	NA	NA	NA	NA	2	57.0876712328767	45.8842609074008
diff --git a/public/biopet-tools/src/test/resources/test.empty.snptest b/public/biopet-tools/src/test/resources/test.empty.snptest
new file mode 100644
index 0000000000000000000000000000000000000000..a5ca28471bb5f836dcc2bd61ca091f1a293c1a0f
--- /dev/null
+++ b/public/biopet-tools/src/test/resources/test.empty.snptest
@@ -0,0 +1 @@
+# Completed successfully at 2016-04-08 13:47:05
diff --git a/public/biopet-tools/src/test/resources/test.gens b/public/biopet-tools/src/test/resources/test.gens
new file mode 100644
index 0000000000000000000000000000000000000000..bec79dab840537cac62c1c009391297ae38e6fee
--- /dev/null
+++ b/public/biopet-tools/src/test/resources/test.gens
@@ -0,0 +1,3 @@
+--- rs1 30 A C 1 0 0 0 1 0 0 0 1
+--- rs2 40 A - 1 0 0 0 1 0 0 0 1
+--- rs3 50 A AT 1 0 0 0 1 0 0 0 1
\ No newline at end of file
diff --git a/public/biopet-tools/src/test/resources/test.gens_info b/public/biopet-tools/src/test/resources/test.gens_info
new file mode 100644
index 0000000000000000000000000000000000000000..250a9677f1bf86cff13d7dee2eba0b9878963b8b
--- /dev/null
+++ b/public/biopet-tools/src/test/resources/test.gens_info
@@ -0,0 +1,4 @@
+snp_id rs_id position exp_freq_a1 info certainty type info_type0 concord_type0 r2_type0
+--- rs1 30 0.037 0.535 0.958 0 -1 -1 -1
+--- rs2 40 0.023 0.621 0.978 0 -1 -1 -1
+--- rs3 50 0.000 0.114 0.999 0 -1 -1 -1
diff --git a/public/biopet-tools/src/test/resources/test.snptest b/public/biopet-tools/src/test/resources/test.snptest
new file mode 100644
index 0000000000000000000000000000000000000000..4ddb3a25b54a638a0d3476670c17bd6cd57ff0ad
--- /dev/null
+++ b/public/biopet-tools/src/test/resources/test.snptest
@@ -0,0 +1,14 @@
+# Analysis: "snptest"
+#  started: 2016-04-08 13:44:20
+#
+# Analysis properties:
+#   -analysis_name snptest (user-supplied)
+#   -data /exports/sasc/project-171/analysis/snptest/18/18-22307785-33461676.vcf.gz /exports/sasc/project-171/src/Phenotypes_knee_hip_hand.fixed2.txt (user-supplied)
+#   -o /exports/sasc/project-171/analysis/snptest/18/18-22307785-33461676.snptest (user-supplied)
+#   -summary_stats_only  (user-supplied)
+#
+alternate_ids rsid chromosome position alleleA alleleB index average_maximum_posterior_call info cohort_1_AA cohort_1_AB cohort_1_BB cohort_1_NULL all_AA all_AB all_BB all_NULL all_total all_maf missing_data_proportion comment
+rs184556815 rs184556815 18 22307810 G T 1 1 1 2869 0 0 0 2869 0 0 0 2869 0 0 NA
+rs143248971 rs143248971 18 22307875 C T 2 1 1 2869 0 0 0 2869 0 0 0 2869 0 0 NA
+rs74666159 rs74666159 18 22307884 C T 3 1 1 2690 177 2 0 2690 177 2 0 2869 0.0315441 0 NA
+# Completed successfully at 2016-04-08 13:47:05
diff --git a/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/GensToVcfTest.scala b/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/GensToVcfTest.scala
new file mode 100644
index 0000000000000000000000000000000000000000..5d4bbc7d8b84434293c6128ef594023909047a62
--- /dev/null
+++ b/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/GensToVcfTest.scala
@@ -0,0 +1,48 @@
+package nl.lumc.sasc.biopet.tools
+
+import java.io.File
+import java.nio.file.Paths
+
+import org.scalatest.Matchers
+import org.scalatest.testng.TestNGSuite
+import org.testng.annotations.Test
+
+/**
+ * Created by pjvan_thof on 4/11/16.
+ */
+class GensToVcfTest extends TestNGSuite with Matchers {
+  @Test
+  def testGensOnly(): Unit = {
+    val output = File.createTempFile("test.", ".vcf.gz")
+    output.deleteOnExit()
+    GensToVcf.main(Array(
+      "--inputGenotypes", GensToVcfTest.resourcePath("/test.gens"),
+      "--outputVcf", output.getAbsolutePath,
+      "--referenceFasta", GensToVcfTest.resourcePath("/fake_chrQ.fa"),
+      "--contig", "chrQ",
+      "--samplesFile", GensToVcfTest.resourcePath("/gens.samples")
+    ))
+  }
+
+  @Test
+  def testGensInfo(): Unit = {
+    val output = File.createTempFile("test.", ".vcf")
+    output.deleteOnExit()
+    GensToVcf.main(Array(
+      "--inputGenotypes", GensToVcfTest.resourcePath("/test.gens"),
+      "--inputInfo", GensToVcfTest.resourcePath("/test.gens_info"),
+      "--outputVcf", output.getAbsolutePath,
+      "--referenceFasta", GensToVcfTest.resourcePath("/fake_chrQ.fa"),
+      "--contig", "chrQ",
+      "--samplesFile", GensToVcfTest.resourcePath("/gens.samples"),
+      "--sortInput"
+    ))
+  }
+
+}
+
+object GensToVcfTest {
+  private def resourcePath(p: String): String = {
+    Paths.get(getClass.getResource(p).toURI).toString
+  }
+}
diff --git a/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/SnptestToVcfTest.scala b/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/SnptestToVcfTest.scala
new file mode 100644
index 0000000000000000000000000000000000000000..e1506b043dcb9623fcc5a3367e53c9a18dff59bd
--- /dev/null
+++ b/public/biopet-tools/src/test/scala/nl/lumc/sasc/biopet/tools/SnptestToVcfTest.scala
@@ -0,0 +1,43 @@
+package nl.lumc.sasc.biopet.tools
+
+import java.io.File
+import java.nio.file.Paths
+
+import org.scalatest.Matchers
+import org.scalatest.testng.TestNGSuite
+import org.testng.annotations.Test
+
+/**
+ * Created by pjvan_thof on 4/11/16.
+ */
+class SnptestToVcfTest extends TestNGSuite with Matchers {
+  @Test
+  def testSnptest(): Unit = {
+    val output = File.createTempFile("test.", ".vcf.gz")
+    output.deleteOnExit()
+    SnptestToVcf.main(Array(
+      "--inputInfo", SnptestToVcfTest.resourcePath("/test.snptest"),
+      "--outputVcf", output.getAbsolutePath,
+      "--referenceFasta", SnptestToVcfTest.resourcePath("/fake_chrQ.fa"),
+      "--contig", "chrQ"
+    ))
+  }
+
+  @Test
+  def testEmptySnptest(): Unit = {
+    val output = File.createTempFile("test.", ".vcf.gz")
+    output.deleteOnExit()
+    SnptestToVcf.main(Array(
+      "--inputInfo", SnptestToVcfTest.resourcePath("/test.empty.snptest"),
+      "--outputVcf", output.getAbsolutePath,
+      "--referenceFasta", SnptestToVcfTest.resourcePath("/fake_chrQ.fa"),
+      "--contig", "chrQ"
+    ))
+  }
+}
+
+object SnptestToVcfTest {
+  private def resourcePath(p: String): String = {
+    Paths.get(getClass.getResource(p).toURI).toString
+  }
+}
diff --git a/public/gwas-test/pom.xml b/public/gwas-test/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..619df649c57eb393b9e29e4873e4019e67003f93
--- /dev/null
+++ b/public/gwas-test/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>GwasTest</artifactId>
+    <packaging>jar</packaging>
+
+    <parent>
+        <groupId>nl.lumc.sasc</groupId>
+        <artifactId>Biopet</artifactId>
+        <version>0.7.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+
+    <inceptionYear>2014</inceptionYear>
+    <name>GwasTest</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>nl.lumc.sasc</groupId>
+            <artifactId>BiopetCore</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>nl.lumc.sasc</groupId>
+            <artifactId>BiopetToolsExtensions</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>6.8</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.scalatest</groupId>
+            <artifactId>scalatest_2.10</artifactId>
+            <version>2.2.1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/public/gwas-test/src/main/scala/nl/lumc/sasc/biopet/pipelines/gwastest/GwasTest.scala b/public/gwas-test/src/main/scala/nl/lumc/sasc/biopet/pipelines/gwastest/GwasTest.scala
new file mode 100644
index 0000000000000000000000000000000000000000..afc6bbdc3ba737db63f5c4270009de0a60b8deaa
--- /dev/null
+++ b/public/gwas-test/src/main/scala/nl/lumc/sasc/biopet/pipelines/gwastest/GwasTest.scala
@@ -0,0 +1,143 @@
+package nl.lumc.sasc.biopet.pipelines.gwastest
+
+import java.io.File
+import java.util
+
+import htsjdk.samtools.reference.FastaSequenceFile
+import nl.lumc.sasc.biopet.core.{ BiopetQScript, PipelineCommand, Reference }
+import nl.lumc.sasc.biopet.extensions.Snptest
+import nl.lumc.sasc.biopet.extensions.gatk.{ CatVariants, SelectVariants }
+import nl.lumc.sasc.biopet.extensions.tools.{ GensToVcf, SnptestToVcf }
+import nl.lumc.sasc.biopet.pipelines.gwastest.impute.ImputeOutput
+import nl.lumc.sasc.biopet.utils.Logging
+import nl.lumc.sasc.biopet.utils.config.Configurable
+import nl.lumc.sasc.biopet.utils.intervals.BedRecordList
+import org.broadinstitute.gatk.queue.QScript
+
+import scala.collection.JavaConversions._
+
+/**
+ * Created by pjvanthof on 16/03/16.
+ */
+class GwasTest(val root: Configurable) extends QScript with BiopetQScript with Reference {
+  def this() = this(null)
+
+  import GwasTest._
+
+  val inputVcf: Option[File] = config("input_vcf")
+
+  val phenotypeFile: File = config("phenotype_file")
+
+  val specsFile: Option[File] = config("imute_specs_file")
+
+  val inputGens: List[GensInput] = if (inputVcf.isDefined) List[GensInput]()
+  else config("input_gens", default = Nil).asList.map {
+    case value: Map[String, Any] =>
+      GensInput(new File(value("genotypes").toString),
+        value.get("info").map(x => new File(x.toString)),
+        value("contig").toString)
+    case value: util.LinkedHashMap[String, _] =>
+      GensInput(new File(value.get("genotypes").toString),
+        value.toMap.get("info").map(x => new File(x.toString)),
+        value.get("contig").toString)
+    case _ => throw new IllegalArgumentException
+  } ++ (specsFile match {
+    case Some(file) => imputeSpecsToGensInput(file, config("validate_specs", default = true))
+    case _          => Nil
+  })
+
+  override def dictRequired = true
+
+  override def defaults = Map("snptest" -> Map("genotype_field" -> "GP"))
+
+  /** Init for pipeline */
+  def init(): Unit = {
+    inputGens.foreach { g =>
+      val referenceDict = new FastaSequenceFile(referenceFasta(), true).getSequenceDictionary
+      if (referenceDict.getSequenceIndex(g.contig) == -1)
+        Logging.addError(s"Contig '${g.contig}' does not exist on reference: ${referenceFasta()}")
+    }
+  }
+
+  /** Pipeline itself */
+  def biopetScript(): Unit = {
+    val (vcfFile, chrVcfFiles): (File, Map[String, File]) = inputVcf.map((_, Map[String, File]())).getOrElse {
+      require(inputGens.nonEmpty, "No vcf file or gens files defined in config")
+      val outputDirGens = new File(outputDir, "gens_to_vcf")
+      val cvTotal = new CatVariants(this)
+      cvTotal.assumeSorted = true
+      cvTotal.outputFile = new File(outputDirGens, "merge.gens.vcf.gz")
+      val chrGens = inputGens.groupBy(_.contig).map {
+        case (contig, gens) =>
+          val cvChr = new CatVariants(this)
+          cvChr.assumeSorted = true
+          //cvChr.isIntermediate = true
+          cvChr.outputFile = new File(outputDirGens, s"$contig.merge.gens.vcf.gz")
+          gens.zipWithIndex.foreach { gen =>
+            val gensToVcf = new GensToVcf(this)
+            gensToVcf.inputGens = gen._1.genotypes
+            gensToVcf.inputInfo = gen._1.info
+            gensToVcf.contig = gen._1.contig
+            gensToVcf.samplesFile = phenotypeFile
+            gensToVcf.outputVcf = new File(outputDirGens, gen._1.genotypes.getName + s".${gen._2}.vcf.gz")
+            gensToVcf.isIntermediate = true
+            add(gensToVcf)
+            cvChr.inputFiles :+= gensToVcf.outputVcf
+          }
+          add(cvChr)
+          cvTotal.inputFiles :+= cvChr.outputFile
+          contig -> cvChr.outputFile
+      }
+      add(cvTotal)
+      (cvTotal.outputFile, chrGens)
+    }
+
+    val snpTests = BedRecordList.fromReference(referenceFasta())
+      .scatter(config("bin_size", default = 1000000))
+      .allRecords.map { region =>
+        val name = s"${region.chr}-${region.start + 1}-${region.end}"
+
+        val regionDir = new File(outputDir, "snptest" + File.separator + region.chr)
+        val bedDir = new File(outputDir, ".queue" + File.separator + "regions" + File.separator + region.chr)
+        bedDir.mkdirs()
+        val bedFile = new File(bedDir, s"$name.bed")
+        BedRecordList.fromList(List(region)).writeToFile(bedFile)
+        bedFile.deleteOnExit()
+
+        val sv = new SelectVariants(this)
+        sv.inputFiles :+= chrVcfFiles.getOrElse(region.chr, vcfFile)
+        sv.outputFile = new File(regionDir, s"$name.vcf.gz")
+        sv.intervals :+= bedFile
+        sv.isIntermediate = true
+        add(sv)
+
+        val snptest = new Snptest(this)
+        snptest.inputGenotypes :+= sv.outputFile
+        snptest.inputSampleFiles :+= phenotypeFile
+        snptest.outputFile = Some(new File(regionDir, s"$name.snptest"))
+        add(snptest)
+
+        val snptestToVcf = new SnptestToVcf(this)
+        snptestToVcf.inputInfo = snptest.outputFile.get
+        snptestToVcf.outputVcf = new File(regionDir, s"$name.snptest.vcf.gz")
+        snptestToVcf.contig = region.chr
+        add(snptestToVcf)
+
+        region -> snptestToVcf.outputVcf
+      }
+
+    val cv = new CatVariants(this)
+    cv.inputFiles = snpTests.map(_._2).toList
+    cv.outputFile = new File(outputDir, "snptest" + File.separator + "snptest.vcf.gz")
+    add(cv)
+  }
+}
+
+object GwasTest extends PipelineCommand {
+  case class GensInput(genotypes: File, info: Option[File], contig: String)
+
+  def imputeSpecsToGensInput(specsFile: File, validate: Boolean = true): List[GensInput] = {
+    ImputeOutput.readSpecsFile(specsFile, validate)
+      .map(x => GensInput(x.gens, Some(x.gensInfo), x.chromosome))
+  }
+}
\ No newline at end of file
diff --git a/public/gwas-test/src/main/scala/nl/lumc/sasc/biopet/pipelines/gwastest/impute/ImputeOutput.scala b/public/gwas-test/src/main/scala/nl/lumc/sasc/biopet/pipelines/gwastest/impute/ImputeOutput.scala
new file mode 100644
index 0000000000000000000000000000000000000000..41574f0cd0aaf2dd0501ab98d5273148f968dd90
--- /dev/null
+++ b/public/gwas-test/src/main/scala/nl/lumc/sasc/biopet/pipelines/gwastest/impute/ImputeOutput.scala
@@ -0,0 +1,80 @@
+package nl.lumc.sasc.biopet.pipelines.gwastest.impute
+
+import java.io.File
+
+import nl.lumc.sasc.biopet.utils.Logging
+
+import Spec.SpecDecoderOps
+
+import scala.io.Source
+
+/**
+ * Created by pjvan_thof on 3/25/16.
+ */
+object ImputeOutput {
+
+  case class Chunk(chromosome: String, summary: File, warnings: File,
+                   gens: File, gensInfo: File, gensInfoBySample: File)
+
+  def expandChunk(chromosome: String, basename: String) = Chunk(
+    chromosome,
+    new File(basename + ".gens_summary"),
+    new File(basename + ".gens_warnings"),
+    new File(basename + ".gens"),
+    new File(basename + ".gens_info"),
+    new File(basename + ".gens_info_by_sample")
+  )
+
+  def readSpecsFile(specsFile: File, validate: Boolean = true): List[Chunk] = {
+    val content = Source.fromFile(specsFile).mkString
+    val chunks = content.decode[List[Spec.ImputeOutput]]
+      .map(x => expandChunk(x.chromosome, specsFile.getParent + File.separator + x.name.split(File.separator).last))
+    chunks.flatMap(validateChunk(_, validate))
+  }
+
+  val ASSESSMENT_HEADER = "-{32}\\n Imputation accuracy assessment \\n-{32}".r
+  val TOO_FEW_SNPS = "There are no SNPs in the imputation interval, so " +
+    "there is nothing for IMPUTE2 to analyze; the program will quit now."
+  val NO_TYPE_2 = "ERROR: There are no type 2 SNPs after applying the command-line settings for this run, which makes it impossible to perform imputation. One possible reason is that you have specified an analysis interval (-int) that contains reference panel SNPs but not inference panel SNPs -- e.g., this can happen at the ends of chromosomes. Another possibility is that your genotypes and the reference panel are mapped to different genome builds, which can lead the same SNPs to be assigned different positions in different panels. If you need help fixing this error, please contact the authors."
+  val NO_ANALYSIS = "Your current command-line settings imply that there will not be any SNPs in the output file, so IMPUTE2 will not perform any analysis or print output files."
+  val CORRECT_LOG = " Imputation accuracy assessment "
+
+  def validateChunk(chunk: Chunk, raiseErrors: Boolean = true): Option[Chunk] = {
+
+    def addError(msg: String) = if (raiseErrors) Logging.addError(msg) else Logging.logger.warn(msg)
+
+    if (!chunk.summary.exists()) {
+      Logging.addError(s"Summary file '${chunk.summary}' does not exist, please check Impute output")
+      None
+    } else if (!chunk.warnings.exists()) {
+      addError(s"Warnings file '${chunk.warnings}' does not exist, please check Impute output")
+      None
+    } else if (chunk.summary.canRead()) {
+      val summaryReader = Source.fromFile(chunk.summary)
+      val summaryLines = summaryReader.getLines().toList
+      summaryReader.close()
+      if (summaryLines.contains(NO_ANALYSIS)) None
+      else if (summaryLines.contains(TOO_FEW_SNPS)) None
+      else if (summaryLines.contains(NO_TYPE_2)) {
+        Logging.logger.warn(s"No Type 2 SNPs found, skipping this chunk: '${chunk.summary}'")
+        None
+      } else if (summaryLines.exists(ASSESSMENT_HEADER.findFirstIn(_).isDefined)) None
+      else if (!chunk.gens.exists()) {
+        addError(s"Gens file '${chunk.gens}' does not exist, please check Impute output")
+        None
+      } else if (!chunk.gensInfo.exists()) {
+        addError(s"GensInfo file '${chunk.gensInfo}' does not exist, please check Impute output")
+        None
+      } else if (!chunk.gensInfoBySample.exists()) {
+        addError(s"GensInfoBySample file '${chunk.gensInfoBySample}' does not exist, please check Impute output")
+        None
+      } else {
+        if (!summaryLines.contains(CORRECT_LOG)) {
+          Logging.logger.warn(s"Impute says it did not run but the gens files are there, pipeline will still continue")
+          Logging.logger.warn(s"      Please check: ${chunk.summary}")
+        }
+        Some(chunk)
+      }
+    } else None
+  }
+}
diff --git a/public/gwas-test/src/main/scala/nl/lumc/sasc/biopet/pipelines/gwastest/impute/Spec.scala b/public/gwas-test/src/main/scala/nl/lumc/sasc/biopet/pipelines/gwastest/impute/Spec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..e8ea1e49b537b4794473d7490610e75d831d355e
--- /dev/null
+++ b/public/gwas-test/src/main/scala/nl/lumc/sasc/biopet/pipelines/gwastest/impute/Spec.scala
@@ -0,0 +1,64 @@
+package nl.lumc.sasc.biopet.pipelines.gwastest.impute
+
+import scala.util.parsing.combinator.JavaTokenParsers
+
+/**
+ * .spec file parser combinator.
+ *
+ * TODO: clean up.
+ *
+ * @author Matthijs Moed <M.H.Moed@lumc.nl>
+ */
+object Spec extends JavaTokenParsers {
+  def obj: Parser[Map[String, Any]] =
+    "{" ~> rep(member) <~ "}" ^^ (Map() ++ _)
+
+  def arr: Parser[List[Any]] = "(" ~> repsep(value, ",") <~ ")"
+
+  def key: Parser[String] = """([\w+])*+""".r
+
+  def member: Parser[(String, Any)] = key ~ "=" ~ value <~ literal(";") ^^ {
+    case name ~ "=" ~ value => (name, value)
+  }
+
+  // This is a hack to get around the fact that JavaTokenParsers'
+  // stringLiterals do not have their double quotes removed. They're stripped
+  // here, without any error checking.
+  // TODO: implement as token parser
+
+  def string: Parser[String] = stringLiteral ^^ {
+    case s => s.substring(1, s.length - 1)
+  }
+
+  def value: Parser[Any] = (
+    obj
+    | arr
+    | string
+    | wholeNumber ^^ (_.toInt)
+    | floatingPointNumber ^^ (_.toDouble)
+  )
+
+  //
+
+  trait SpecDecoder[T] {
+    def decode(obj: Map[String, Any]): T
+  }
+
+  case class ImputeOutput(chromosome: String, name: String, orig: String)
+
+  class ImputeOutputMappingDecoder extends SpecDecoder[List[ImputeOutput]] {
+    override def decode(obj: Map[String, Any]): List[ImputeOutput] = {
+      val dicts = obj("files").asInstanceOf[List[Map[String, String]]]
+      dicts.map(d => ImputeOutput(d("chromosome"), d("name"), d("orig")))
+    }
+  }
+
+  implicit val imputeOutputMappingDecoder = new ImputeOutputMappingDecoder
+
+  implicit class SpecDecoderOps(string: String) {
+    implicit def decode[T](implicit decoder: SpecDecoder[T]): T = {
+      decoder.decode(Spec.parseAll(Spec.obj, string).get)
+    }
+  }
+}
+
diff --git a/public/gwas-test/src/test/resources/fake_chrQ.dict b/public/gwas-test/src/test/resources/fake_chrQ.dict
new file mode 100644
index 0000000000000000000000000000000000000000..e2b0e2af7579a994afedb68a5c495ba794a445df
--- /dev/null
+++ b/public/gwas-test/src/test/resources/fake_chrQ.dict
@@ -0,0 +1,2 @@
+@HD	VN:1.4	SO:unsorted
+@SQ	SN:chrQ	LN:16571	M5:94445ec460a68206ae9781f71697d3db	UR:file:/home/ahbbollen/fake_chrQ.fa
diff --git a/public/gwas-test/src/test/resources/fake_chrQ.fa b/public/gwas-test/src/test/resources/fake_chrQ.fa
new file mode 100644
index 0000000000000000000000000000000000000000..171b3737bd458bba03d7c457b6ba51e5ef4f774f
--- /dev/null
+++ b/public/gwas-test/src/test/resources/fake_chrQ.fa
@@ -0,0 +1,2 @@
+>chrQ
+TCGGCATCTAGAAACTCCAAGTCTGCAGATCTATAACACACGAGGGTATTCAGCCCTAAAGCATTGCGTCTAGGCATGGGTCTTTAATCTCGCCCCGGCAACCTCTACGCGAGCTCCTACCAGTCAACGTGATTGATCCCTCGTACCTAGCATATTCCACGGCGTTTCATAGCCTTGACGGGCACCTTATCCATTTTTACCTAGTTTGACATTAATTGCTTCAAGACTACTGCGGTACGGGTCCCTGCATCCAGAAAGGATGACAAAAAGTGTGACAGTGCGTTCAATCCATAGATTCCCGTCGGTGCGAGGGCTGAAGTTGAGCCCTACAACCCGGCGATAAAAATTGTAACCCTATGCATTGCGTCAAGTTAAGACCCTCCATCTTCGCCACGCGATAGGAATTTGAAACATCGGCGTGCTTAGAAAGGCTATTAGCGCGGGTGGCCTGATCGGTATCCGATAAAGGCGTTGCCACAAATTTTGCCGATTGACCTGCAATTACATCGGGTAAGTGCATTTCCGCCGTTAGAGTATTAAGTCATGACGTTTTCGACATGGGCATTTAATTGGCCCAAGGTGGAATATTCCTGATGTGCCTAAGTATGAGCTCCCCATGAGAATTTGAAGATCATGAAGACTTGAGTCAATTCTAAATGTAGTTACCATCACTTAAGTTCGTTCGCCTTCTGGGCAGGCTATGTCTAACGAGCGACGTCCGCAGTGTGACAATCTAGATATTGGTTGAGCAGGAATACCAAGGAGGTGCTTGAAGTTTCTCTTATGGAACCAACTTCAATCAATAGGTAGTCTCCGTTTCGTTTCCACTGAGACATTTGTGCAGTGGCACAGTATGTGGTCGTAAGCGCATGGTGTTGTTGGAACGAAGACTCTCACTTTTGTTTCCTTTGGTAGTTTAATTTAGCAGTATCCTGGTCGTTGACCAATTTGTGAATCTCCACGGTCTCTCTTTATCAGTCATACCTCTTAAACCGGCTTCCGCTCCTGCGCACATTTATATCCTACTTTCCGTCAATGTGAAAGAGAGATCAACATAATTTCGCGCACGATCTGTCCCATTTCAGACGCCATCGACGGGTCCCGCCTTCACAAAAAACCTGCCACCATGCAGTAGGTACCTCCATATGCTGAGCGTCCGTTACCGGAAGGGTTAAGTCACTGTTTAAAGGATAAGGCGAGGTTTCCCTTGGTGGTGTACTACTGCTCACGTTCCTGCTTTACTCTCCGAGTATTGTTTTAAAAGTGGGCACGCTGGAACGCAGCACCCTATAAGAAGACTCAGTTAGGTCCCCTTCACGAGCATGTTTGAGCTCTCGGACCTAAGACGTCCGAACTCGGTTACGACGGTTAAAGACAAAGCTCCCAGCATGGTATCAGAAGCCACCACGCGTGAGGATGGCGGGGCCCTGGGCACATTGGCCCCGAATTCTTCGCCCACTTAAGTCGGACTCACCACGGGAGACTACGCCCTAACCGGATAATATCTTTTAGATACCATACAGGGTGCAACCATCGCGGCGTCAGCTGAATGTGAGGACAGAGCCCCACACACAGCACTAACAGATCCATGATTTTACTTCGTTTGGGCGACGTGCGAGCCTATTCGGCCTGTCGGACTTTGTGTAGATTCGGGATTTGACCTAGCGTATAGGCCTTTGGTATACTCGAATTATCAGGGTCAAACTACCCTCAAGGAATCCTATTTCAGACGGACGTTTGCCACCCCGGAACGTTGTCGGATCGCTTCTTGCCGCAGGAGATTCATGGAGTGATAATCGCTGGACTCACAAGTGTCAGCGGACTTTCGGTGTCTTGTGGCCTACTTGCAGTGAACACCACCAAACGAGTAGTATTATGGATTGCCGGCGTGTGTTTGTGGCCATGATTGGTTGATGCGACGGCCTAGATTCTCCTACGGGAATCTACCAGGCCCAAAAGCGCTGACTTTTATGTATTTGAGGGGCCGAAATTACATAGTAACCCAGAACAAATACCCGTTAGTTATAAAGTGAGCGCATAAGTTTGGTCGATCCGGCAGTCGAACCATTGCGGTCGGACATATCCGCAGTAGTACACTAAGGCGGAATAGACTGCCGAGTCAACGCTCCCTCATTCTTGCTACCTTAGATCTCGCAGGTTCGACCATTGCTGAAGCCGCTGAATTACACGAGTTGTTTTGTTAACCCCCGGAATGTAGTTCGTACGCCTCAACTGATTCTTCAAAAGCTCACTGCACGTGACTTGTCATGTGTTCCTAAAACATACCTCATCTGTGGGTCTGGTCCCATAAGCATGGAATGTCCGTCGACGCAACATGGAAACCCACTCGCTCGCTATACGTTTATGGTGAGACAGAAACACACTGTATTAGACTGCCACTGATAGCCCCAGTAGCAAGGTGATGTGGCAGGCATGGTACCCAAACGTCTATCGTTTTGGGAACCAAGGGGAGTGCTAATAGGTCCGGCCACGTAGAATGACATAACCTCCAGAGGAGCGCAGGAGTTGATGCATTAAAAGATCCATACTAAACGTTAGCTTAATGCCTTCAAGGCACCAGCTACCTCCATGACAAGGAGATTTCGGAAGGGGTAAGATTTACTTCTGTCCCAAAAGGGTAATGACCCGTAGGGATGGAATCATTGATGAACTCTAAAGGGACTCAGCCGACTAGCCGAGAGGGCTGGACGATCATTTGATGGGAGAATACGCATACATCTAAGTGTCAAGTATTAAATCGGTAATCTCCGTAAAGGCGTGAAGTTCACAGGGCGCAGTTTCCAGTTACTCCAAGAAACTACCGGTTCAGTTATCGCTTCCGGTGCCTTCACAGCAAACATCATTCGCTCAAGAAAGTGCTGTCGCTGCGTGTGGATATTTCCCCCTCGTTCTGGAAAGTGCTCTCAGCGACGCACGTAAACATGCTGGCGACGAGAGAGGCGTCAACACGGTCCGTTACCAAACTGCGGCATTTACCACGAACCTGATTGCAAAGTGAGATTTCCGTAAGGAGGTTAGCCAAATATTACGTAGAGTGTTCCACACCAAATCCGTCGTCCACATTCGCGACGGCAGTCTAGACGTGTAATTCCCCGGATAATCCAGTTACTACATGCTGATGCAGTCATAGTGCACGCAAATGCGCAACTTAACAAGCACGACCTGAAACAGAGAACCCCTGTGTAGTCAATATAGGATGACGGACACACACACTTGCTGCTGCAATCTTACATTCTGCGAACGAGTGCAAAGTTGAAATCATGACGAACAGCCTTGCTTTTCAGAGTCTCTATCGAACTCCTTTACACCTCCATATCTACTTGCAAATCACACTAGAGGGGCGCAGCTTACTCACTGAGAGATGGTCTACCTAATCGATTTTCGGTGAACTTTGAGTACAGCATTGAGTCTGGAGGGTTCCACTACTTTATCGTACCGGTCCGACATGATTTCTTATCGAATAGATGTTGAGATGGACATTAATAAGCATAGTACGTCTCGATCGATGGCTACCTTTACGTCTATGAGTGCTTACATAAGGTCTCTCGTAAGTCATGGTCCCGCGGGGCTCGCGCAACATTGTGGATTAATGACTCCAGTGACGCATGTTCGATTCGCATGAAGTAGGTGGCGCGTATTCATACATGAATAGTAGGCAGAACGAGCACATTGGACCGATCTTGGAGGTTGGGCTTGAGGTCCCGCACTGATAGTTTACGGCCATGAAGACGACAATTGTCAATACTTCTCTATCCTGAGCGAATGCTGACGGGGGCCAGGCGGAAAAGTGCGACACAGTCTACTGATTACGTGTAGTACGTGGCTAAGCATATTCCCGGGTTCGCAAACATAGGTCTCTGATGGGGTATGGGTAAGAAATCTGAAGGTTGCGTCTCTCACCACGGTCAGGATACCGAATCAGCTCATAAGAGTTACAAACGCGCAAATGAAGGCCTAGTCCACAGGGGTGTCATTCGCACGAGCTGGGCTTAGAATCACTGTTTTCGGTCGCACCTGTAGGGGGACATGGGACGGATTTCACAACAAAAAAGCATCTCTCATGATTCGATTCAGATAGAGGAGAGGAGGTAAATGCCAACAAATCTATTCTTTAGTACCGCCTGACGGAACGTATTTAATCCTCGCCTCAGATCGACACCGCAGGGTAGCTGAAGACGTCCGTTCTTAGACATTTAGTCGATCATTTGTTATGAAACAGAACTAGGAGTCCGTGCCCTTCAGGCCGGCTCAGGGGCACCTACCTCCAGATCGCCCAGGTTGGGTTTATTAGGCGCCGAAAAGTTACTGCCCTATCAGCCCCTCCAATCCGACCTACGGACATCATCCCACTGGCTCGCAAAATATAAATTGCGGATGGGAAAGGATAAGGAAAATCATTACCTACACAGAAGGACAATGTCAGTTCCAAATAACACTGATACTTTCGGAGCAACTTGGTCCGGAAATGTAAGTACGACTATAGCCCTTTCGACCAACGCCGACAGTCCTATTTGGACGCCGAGAGAGGCGACGGGTAGCCGAATGTAAAGCTCTCGGGTCGCTCTTGGCGGAATGCGCTGCGGGTCCTACCCTAAACCCTTACCACCACCAACTTCGTTAGGAGCCGTATAGATTACAGCTCCCGCAAAATTAGAGAGGAATCTGAGTTATTAGCTGAGGACCCCGCATTTTCTGCGACGGCGTAGCTGCAGTGACGTACGATATGAGTTCCCGACTGTGAGGGAGTCCCAGTCGTGACTCCCTACAACGGCTCCAGATATTGTTACTTATGGTCAATATGCCCCGACCGCCCATTGTCTCGAGTACAGTCTTCCCCAAAGTTAAGCTGTGCATTACCTTACCGTTTTAGGTCCAGCTGGTAGCACCGAATGCTGCGCAATCCGAGCCCCCGAAATAGACTACGTGTCCACGGTCAATTGTCATGGGTAGCAGAGCTCAAAGAGGAGAAACGTGCCCCGTAAACCTATTAGATCTCGGTTGATAAATATCAGGCCACAGCAGGCTGCCCGATGCTTGTTTGAACAACAACTTCGGGAGCCGCGGTCCTTGGTTCTCCCGATATTCGGCCGCACCGAACGGTACGCGTCATCGCGAGGTGCGTTCTCGCAGCAAGAAATATTTGTTGTTGTTGTCTTCCTTCCGCATAGGAAACCTTAAGCGGTACCTTTCTACGAAGTTGAACCCTAGAAGCACGTGTAACAATTTTTTTTACGCTACACCCGGATCTGCTTCCATCTGTTGATCATATGAGCCTAATGTGACTAATCTGTGCCGTCGATTGAAAATTCGTTCTGAACCTAATCACATGAATTAAAATTAGGGCGAGAATTGGCTCCTTTTGGGCCGTAATCCTTCAAAGGGTTAACCGAATTTAGCCTCCACGGTGACACAAACTCCCATAGGTAAGGCAAACCCAATAACGAGGAAGCCTTGCCCACAGCATGTTTGATAAATACCCTTAGGGTAATATCGCGTGCAATACTGAAGCCGCTCTTCTAGCATCCGTGTTTGACATACTATGACCTTGAAGCCTGCCGCAGCTTCTAGGTCATCCAAGTAGATCAAAACGCCATGTTGTGGATCCATGCATCTTCCCAGTGAACATGGATCTTAGTGTGACAGGCGAGGAGCGGCGAACACTATCGGTGTGGCAAGCTCGGGCCTTCGTACGTTGTGGAAGTATGCGAATAAGGAGACCGTAATGTATCAAGTTCTTAAGAGCCTTGGTACCGTTGCAATTCGGCATGTTCCTACAGAGACACTCCGTGTTTGTCATCCGTCATAGATCTATGGCGTAGTTAGCGCCTCTGAAGTAGTTGTCCATTCAGCAGGCATTGCTTAGGGAGTTTCTGGCGCTTGCCGCTCAAGATGCTCACGGGCCTAAGTAGCACGGCAACCTTTTGACAAAGCATTTTATAAACTGAGCATATTGGCCCGAAACTAATCCAGCAAAGGGTGAAGACCTGTCAGCGGGCCCAGAGTGTGAACGGTCTACTGCGCGGTACATAAGTGGCGTAATCCATCAACAAGACCTACACGACCTGAATGATTTCCAACAACTTTATATGCTTTTCCGCATCTCGAGAGTACCGGAATCTATGCAATCTCCCAAGGATCCGTAGATTTGAAATTCAATCCGACGGGGTAAGGTTGCCGCGCCGGTTAGCTAATGTGCGGATTTATAGTCTTTTTCCCAGAAGGCGTAGTTAGTTTCGCACCTAACTACGACACATACTTGGGTCGACTGTTGAAGGTGGTAAGTTGCGAGCAGTCCGCCGCTCTCACGCGCCGAACCACGTTCATATCGGCAAAGTTGCGCGATGACCTATAGGTGTGCAAAGCTCGTCCGACATTGGGATTGGATTCACGTACATACGTTAGTATCATGGGTAAGCTTCCATGTCAGCCTCGTGTATAGCACCGGTGCGCCGCGCGTTAAGGATTCTATGCCCAGCAAATGTGCCAACGTTGTGGGGAGAAAAGTGTAGTTGGATGCGATCGTGACATCGGCACACCGAAACTCTGCAGCCAGTCCCGCTAATCTCATTGGCACCGGGTAAGAGATTACCTTTGGTTAGGAATCGCGTGCGACGTACTGCACGAAAACAGTGCCTGAACCGAGGTGTTTACTTAGATGGTTCTAGACCCAGCATGTTCCTCACTGGAACCTGACGTCGGTACGTGATCCTCTATACCTCCTTTTCGGTATTGGCCTGGCAGCTACTCTAACTGTTTGGGCCGCGCCGATTTCTCGAGTCCACACGGCGAGGTCAGCAAAATTGCCAGTTAGTGGATGTTGGGATCTCAACGCATTACCATGAGAGTTCTTGGTTTACCCGTTAACATCGCTGCGCACGGTGTGAAAAGCCTGTTTCTTTGGCCCCCATCATCTTCGGCCCGCAGATCTCAGATCAATGATGTAAGGTTGCGGCGGCAAAGACTAGACTTGAGTCGTGAGATGGTGCTTTGCTGAGGCCGTCTCCTATAGCTTATTCTAGGACTTTCCGCAAACCACCCGACGTGCGGCTGTCCACGATCGGATTCCATTCTGTCTCGGAGCATACAGCACTAGATTTGCCGCTTGAAAAATGTTCCATAACCATGATTTCAACCCCATCTAGTCGGCAGGCACAGCTGAGAACAGCGAAGGGCGTCGTGAAGGGCATTGCCCGTAGTGTTTCAGACGTGCTAGAGACTAAATCAACTATCTGCACTCGTAGCCTGGCGTGTGAGATGTCACCACGATGTGCCTAGAGGAGTGATTATGAACATGTATTACCACGTCCGGGTGTCGACGGCTATATGGCTAACATTTCTTATGGCTAGACGTGCTTGGAAAGGTTCCCCAGCCTTCTGTTTCCCGGTGCTTTCCACGAGTCTGGAGTTCTGGTAATTAACTACATGGCGTTAACGCGGAGGTAACCCCCAGTCATTGCATTGCAGGTAGGGCTTAGGTGCAATATAATTCACCAAGGCGCGGATTCCTCACGATTGTTACGAAGACACCCGGAGGGTTTCAGTATGGCTTGAGAAGTGTACGTTTTTCCGGCCAGGGTGTAACTATAACCAACACATGTTTGGCCACGGGCTAAGTCGGTCCGCACGACTGATTTCCCCCGCCCATGTGTTTGGGAGCAATAAACTGCGTCTGCCAAGAGTAACAACTCGAGTAGAGAAGGGAAGTCTCAGACTATTTTGCAAATCAGACTGTAAGGCTCAACAGCCATACAGCTTGCCCTACTACTGAATACTAGCGTAGCGTGGCCACATAGGAAAGACTTCATGTCTTCTAATAACCTTTTACCTCCAACGTCCCCGCCGTCTTCACGCGGTCCAACGATGAGGAAACAACCACCCCTATCTTCCGCGGAGTGGTTCACACGACCCCCGGCGTTAACGCGCACGTTGTTGTCTTTCGGGACGGCACTACCCCCAAATGCCCAGACCCAGTGCTAGCGATATTCAAACGCCGTCCGGTAAGTCCTGACGTTTTTCAACTGGATGCACTGGCGACACGTAGTTCGCAAGGCGTCCATGAGAGGTTTTAACCGTCATGTTTCCGTATCACGTCTTATGTCTGTCTCTATTCTCAGCGAAATTCTCATCATAGGGCGGAGACTATCTGAAGGCCAGCGAATACAAGATTTAATATCAAATATAGCATGGGGGCCAACAGAGGCCCCCCTGGTGCTGACGAATTATCGTGATATTAGTACAGCTGTCTGCAATGCCATTTCGAAGGCTTTTTGTTCGTATCACTGCTCTATGCATAGCGGTCACTATGACCTCTCAGCTTGACTCACCCGAATGACCAATTGTGGTCCAGCACTCCCTCATCTTCCCCCATTAACGATACGTTGGGCACCATCGGTGTGAGCTACCCGTTACAGTCATAGAATCGTTCTTTGCGTTGTACGCGGCACGGAGGTGACCGGGAAAAGCGCCGCGAAGGCCCCGCACTGAATAAAGCTAGTATTAGCGTCTGTCAAAGTGTTTTGACACCTAATTCGCTTCCAAGTCCCAATATCTAATCTAGCCTGCTTTGGGCCAACATCTCATTGCGTTATGCTAATGAAGAGGGTGCGGGATCACATCCGCTCTTCTCTTCCTATACACAGCGGACATTCGGGTTGGACGTTTGGAGTGATAATTTATCGTTAGGGATAAGTATGTCGGCGCTTAGTAGTATAGCCCGCTGACCAGCGTTCGATTTCGAACCTTACTGGACATTCTCAATAACTACTGATCATGACGTTTTCCTCAGTTCCTAGCCTTGACAACTAGCCACAGTCAGCATGGTAGAGAGCGTTGAGCCGGGGATAGCCAGGCTATTAAGACAAAGACCCTCGGGCCCCTTAATGCGCGTCAAGTCTGACGGTTTGAGTGCGGAGCAGTAAGCGCTTTGGTATAACCGTGACGTAGCAGATCCATGCTTCGCCCGCTTCCACCTGAGAGATACTAGCCTCTTTCGCACTTTGTAGGATTACGGGCAGCGAAATATTTATCCTGTGCGGCGAGCCCGCTTCGGTTTCGAGCTCTATCAGTGCGCGGTTGGCACTCCAACGCACGATAACATATACCCGCCCACAAGGCCATGCAGGTTTAACCTCCTATTCTGATTGTACCTGGCTGACTTTACGGTACCCACCAGCGCAGGATTAATAGCCTAATTATGCTAACCGGTGCTAGTCTAACTGCTGTTACTAGTCCGCCCCAGCTACCCCACGGGTCAGTAACTGCACCAGCAAGCATGGTTCTCCTCCTGAAGTTGTACGTTCGAGAACCCCGTATCGAGTTGGTATATAAATTAAGGGTTGTCTAAAACAGAAGCCTATTCCGCTATCATCGGTGTAATAACTGATCGCGCCGTGGTTAAATGGAGGAGCACCCGCATGGATACATCGCTAGCGTCTTGTAACTCTCTGGGGGCCTAGTATGGAACGGAACAATGACATCATTGCTTACGGGGCCCGCACTTAGCTGTCGCGTATCGCAAATCATATGGCATGTCAGTCCCGACATCACGAAAATGACCCCATCTGAGGTGGTCGGGAGGCGAACAGTCGAATATGATGTATGCACCCGCAACTTAATGTTCAAAGGCGGGCGAAATGCCTTCTCCCGTCCGGACTATCCTGAGTGCTAGCCGCGAGTCTGTAAAGGTTGACGCAACCATATAGCACGCAGAAAAATCACTCTCACACCATGAGAACCATGGCGGCACGCTGTCTACTTTGTCTGACAGGCTACGGAAGGAATGGTACATACGTACAAACGGATGATATGATATCGGTCATTGCCTATTGTGACGCTACCCTACTGCATCACCCCCTTAGAATGCGTTGGACGCTCTATAGCAGATCCTCCATCCAGTGGAAGTCTCGTCGCCGTGGTTTGCCTTAACGACCGTTGGAGAGAGCAGGACAGAAATATCGCCCTTTTGAGCGCATTATTTGGAATCGAGGTAAGTCAGTGCGGCATAATCGCGCCTCGTGAGCGGAACAGTTTTTGATCCCACCCGCTAAATGCCAAGGTGCTGTAACCTGGGCGCGACACCAAAAGACCACGTGCTGTATGAAGCATGTGTTCTAGCGCACTCTCAACCGTTACCCCGAGAGTAAAATGTTAGTTGTAGGCCGATTCTGCAATGGTAATTGGCGGAGTGTCTAGGGAAATGTTTCGGTCATACTTAACCGGCTACCTCTTCCTCCCTCAGATTCGGTCTGAGATGAGATATACTGGGTGAGTTGAGTCGCCCTGTATCGTTGCGGCGCTCGTGGACCAGACAGACAGTTCCCGTTTATCTCTGCTTCTAGATGGAGGGTCGCCTCCGTGTTAACGCCGGCGAAGGTAGTCGCAGCTGAAGTTGTGATGCACAATCAGGTGAGCCTTTTAAGTATGGTCCTACGGACGTGAACAGCTGGGCCCAGTCATTTAGTACGGGGGGTTTACCTATAAGGATACGGTAAGAACGTCATCTATCCGTCCCACTGGAGTCCGAGGGGTTCGTGTCTACACGGATTACTTATCATGCACACACGTCTACGGTCATGCATAAAGTTGTGCAGCGCAGCAATCGGAGCGGAGTTACACCATCTCCCTATTAACAAGGCACTTATTAGTACTTACCCCGTTATAGAGCTCTCATCTTATCGATAGAGCGCAGTCCTAAGTATTGGCTCGAGTGATTCGCTCCTCAGCCCTTGATTGTAACTCCCCCGATTGCAGGTTGTATGGTGAGTAAAATCTCTGCGCCCTTCTGTTCGGATAAAGAACCCCGACCACTAATGCCCGCCTGCTTGTTGGGCGGTAAATGGGTAACGGAACATGGACTATGAGTGCGATGATGGTCAATAGAATTACCTTATTACGCAGTAAAAGGAATGACGCAGACAGGTATTTGTCGACGATTGCTTCGAACCTGGCAAAATGGGGAGGTATCCTGTCATGTTCATCTGTAAAACAACTCCTGCCTCTTCGTAGAGGACACACACTGTGGGCCTTTAGCCTTTAGCAGCCCATTGGGGCTTACCAGCTGTCGTCATGGGGTATCATTAAGATCCATGCGCCCCCGAAACTTACTGCAAAACAATATGGCTTAAAGGTAAAGGGACCATCAGGAGAATGCTTAAGAGCGACATATAGATACGTATTTAATTAATTTATGTTAACGCAACCATCTCGCAGGAGTCGCATAGCATATTGCCGGGTGATAGTTAATGCACTGTGCTTCCGTGTTTATATAAAATAAGCAGTAACCTCTGACAGGTTGAGACTCCAACAAGTGCTCCGGGTATTTACCTTCTACCATGGCGTTCTAATATCACGAAAGAGAAATTGTGTGTACCGATGCCAGGTGACCGCCCGCGTGCGCCAACGACGCAATCTAGAGCATCCACGCTGAATTGGGGAACTCTTGCCGTTCGTCGCATGGTGTACTTGGTACCACTCGATATGCCTGATTAGGTTTGGCCGTAGCACGTAAGGTAGTGACTTTCCATTCAAGCTAGCGAAGCGACACCACCACAGTGCCCGGTCAAAATAACCCACACCTGGCCAGCATAGAGGCTAAAATAGCTACAGTGCGCTAATCGAGTGTTTTTGCATCGGCTCGTGGCTGGTGGACTCGGGACAGCTTAGAACTAACTCTGGTGTACAAACGCGATCGTAGCTCTCGCGACTTACTCACCGGAGTAGGTTAGATGGACAAGACCTAACCCGAAGCCTAAATCGCCCTGAGTGTTAGCCGCCATTCAATTCTATGGTTTATCGGGGGCGTCTATGGCTGCGACAGTATGGAGGCCCGTTATGGGCACCCGAGTATCGTACCATAGTAATCCCATATTCCTCTTCGAGCGACTATTGGATCAACATACCTACAGGGTAGTATGAATGTTCTTGATTACAGAAACCATGGAATCGGCGCATTCTATGTTTCACTTCCGAATAACAGTGAGCAAGGCATGCCCTTGACAAGGATCATCCCGACAGCAAGCCGATCGGGCCCTAGAGCCCGACCCCCAAACAGAACACCGGCCACGTAGTTGCTGGGACTAAACAAAGGTGTGTTTCCATAAAAGGAAATCTTCAAGTGTATTGTTGAGTCGTAACGCTTATATTTATGGCCCAATGGGCGTTGCGAGCACAGTAGCAGGCCTAGATGAATGCCTAGGCCACGATCGGGGGGAGGCTCATTGAACGTACTGCCATACCAAGCCCCCGTATGCTATGGCAGGAGGGGTTCTCTTCGTATAGAGCGAGGGTCTCTACGCCAAGCAGCATTCCCGTGTTGGGTGGCCAATGGGGCTCACTAGAAACTCGGTTTTTTTAGCGAAGGAATGAGCAAACTCGTGAAAGGTGGTACACACCAGTTGCGGCCGATTTGTTGTAGCAACAAGGTTTGAAGAATTGAGTAGATGGGCCAATTTACCTCCTATTTAGCGAGTGAGATGGCGCATGTTTATTCAGACTCCATGTGGGGTAGAGGCTAATCGTTTAGTAGCAATAACCCCGCGGGGCAAGAGACCGTAATAACTTGAATCTGTGGTAGCTATGAATATGTGCTTCGCCCTAAGTGTTATGTAACAAGAGTGATCCAGGGGCTCAGATCACACTTAGTACGATCCGCTACTGAAATGCGGCCGCGGGCTTGCACGCTGGACATAAGTCGGATAATCAATTGCCTACGACAGGTTCAGCCATAAGGCTTGGCTCCTAACACACTCATGATGTCTGGCTTTTACTCGTGCCCGGACATAAACGTATGCTCAAACGCGAGACAGGGGAGGGTCAGCACCGTTTAGATCTATAAGGCCTACCGGTAATATGGATCGACAACAAACAGATGCTATAGGGATACCTACTCCTTTGGACCCACATGTAGATGAAGGCAAACACGCAGAGCAAAGGAGAGTAGTCCACCCGGTATAAGTTTGTGCTTTGAATTCTGGCTACGCAGACTTGCACTCTGTCCCGGCATTCACTATACTTCTCCGGAAGTCCTTTAAGAAATGTCCGCGCTCATGTGGTTCCCGTTGCTCAGGGGCCAACTCAAGTAGATCTTTAAGGCGCAGTCGACCACAGGCTACTAGATACGAGTTATACTTATCCGGACATCTGGCTAAATACTTGGATACGATACTTCCCCAGTCGTGAGAACGAAGCTAATACAGATCGAATTTCGATGGTTCAGGCAGGCAGTTCTCAGGAGGCAAGGTGTTAAATAGTTTCGGAGGCTCTTTCGTACGATCAGGGTCTACTACCCTAGGGCATTTTGACTTTGGATTAAATATGCAAAATGCAAGGCCGATTGTGATCAGTACTGATACTCCAACTGGACCACCTTCAGACCCTTCGAGGGGACCTAGACGACGGGAACCCTTCCAGCGGGTGATACCAGTTAGAGCAAGTCACAAACACGATTCAGCCCCCGGGGTTTATGACGTACCATGCGAGTAATAATGCACGTATACGGAGCTCTTCCACCGAGCGATGGCATTTCGGGGCGAGGTAGTTGTCTTTCATTGGCATCGCACAACCCCCATCCTCTTAATTGGCATCGTCTCCAGCTGGAAAGAATTTGAGTGAGCATGTCGCCCCTATTATTCCGTTGCCAATAAAGTGTCTCAACTTTTGGCGAAGGTTTTAACGCATACAAGGAGAAGCCGCGAGACGTCTGTACCGCTGATCTGGACGCAAAGTGCTCGGACTGCCGCTGAGTTATCCTGGACGCCATGATTAGAGCCGTCGTCACTACCTGCATACATGGGCCGATAGAGTACTGCAACCAACAACTCACTTAAGCTCCACAACGGCTGGACACTTCCGAGAGCGGTCTTACACAAACGTTAGGTCCTGGGCCGCCGACCTTACCGCTAGTTAGTGAGAGCCAGTTAAAATTATGAACGCTCGGAACCTTCCCAACAGTGGCCGCAGCCTTCCTTGACGCCTAGCACATCTGGTTTATACTCGGGTATGCCGTAGATCGGTAACCTAGGGAACGACCCTGTGGGTTTAACACCCGAGTGCGTAATCAAGCCTAGAGGCCATCTCAACTCGAGAGGTCTCCTGACAAAGAGGCGCCCGATGAATCATCCAGAGGCGTCTGGCGGTCCTACGAGAGTGGCTTTGGATGCCTGCCCCTTGGATGGATCTGTCTTTAATCGGCGCCAATACCTAGCACTGCTAGGCTCCAGACTGTGTTTACATGCCGTAACCCTGATACTCGCAGAAACGTTGCTGGAAATTCCTAGCAGCTGAAACCATTCCCCGTAACGTACTAGTACGCTAAGAGAGAGTCTCTCCTGGCCCTGATGAGTGTGTTCTCATCTGGGGCACGATACAAGAATCGGAACGAACGCAATGCCGAAGTCCCTTGTACCTTAATTTGGGCGACGCAGATAGACCCAAAGATCGCGGACTACGGAAACTAGCATAGGACCTGTGTCGAGAAGGTTCGAGCAGGTAGTGACACGCAGCGCGGTGGCCGGCGGGGTGGCACATTGCGGGTCAATACTGGTAGTAGCCACTCTTTGGACATAGCGGCGGACCAGCGCCTAGAATGTCTCATTCTCATTTTGTTCCGTGGCACGTTACGTAATGACGGCCCGCCAGCACCTGTGTATGGACTTGTAGCTCGGGCCTCTGGTCCTGGCACGACAAGGCACCAGCCAGTAATCTCTCCTAAGGCGCTAGCGTGCATAGCGCGTCTGCCTACCGCCAGAGAACGCGTCATCTGCAAGACGTCCCAGCGTAGTGAATTGTAACTGCAAGCGTTCTCTTACGGTCATAGTGCCGATTTTGAGCAGTAATGGAAGCAGCAAAATGCCGCCCAAGCGATTCGCAAACTTCTAACAGAGCTACAGCCGGACACGACGCGGTGGTGCTCGCGGTTGGTGATCTTATGATATTAACGCCCATAGCGGCCATCTTAATCGACACCATGTTCGTTTTGGCAGGCCTTGTGGTAAACACGTGCTAGTGGCACCACCCATGCCCGTGCCCATACATCCAAACCGAGAGAAAGCCTATTTAAGCGAAAACCACAACTTCGAGGTTTCACCCCCTGCCATTGATAAAGCGAGGAGTACCCCCGATGCCGGGAAGCGTCCGCACCCATTTCTTTCGTTCTGGAATCCTCGGGCGACTTCTCGAAGATACTGTGCTCACGACCTGGAGTATCATGAACAATCGGAGGAAAATGAGTAATTGTCGAGTCGTTGTTAGACGGCACTTCCGTCCGGCCCAACTGTTCTCGGATACGTGTCCCGTGGTCAATGCTCTAAACCGGCTGCCGGCGACTCAGTTCACTGAGACAAATTCTGATGCTTTCGAAGCAAGGATGCGCCCAGAGCAGAGCTGCCCAGATGAGGTTAAGAACGTAACTATAATCGATCAGCCATTCGGCTTAAGGGGCCCCGGCGAAACGCGAAACACTTGGCACATGGACGCTTCACGCGCAACAGTAGTTGTCTCTTTCGTGAGCCACCGTAGCAGCTAGAAAGGCCTATCCAGTGATGCTTTATGACTGAGTGTCGAATCTAGGTATAGCATAGACTGGCTGATCGGGCGGGTCGGCCCACCCGTCTCGGTCGAGCGGTTCTGACTTTGGGTGGCTGTGTGAACCCAACTGCAGATGGAGTTGAATGGGTACACCCTATGCGAGGCCTCGTCTTTACACCAAATCGGGGCCCTGTGAAGTGCCACTCTTTTCCAGCCGGCAGCCGCTCAGTCTGATTTTGCTTGTACATGTCGTGTGCGAACGTTCCGGGAGGCTTCCGTGTTCCAAATACCGTGTTCTCATATTCGGTCCATCTACCGACGGAGAGTTGGGATGCCCGGGCCCGGAAATATAATTTAAACTCGTGGCCAAGAATTTAGCATGTTGTAAACATGAGAGACAGGGCCGGGCTAAAACATTACCCCTGAGTAATGTAGAGCCACAACTGAACATAACATTGGGATCTAACGCACGCAATCAGTGTAGCTTCAGCCCACCCTCTAAATTTCCCCCGGACAACTGGATTATCACCTGCGTCACGCGATAATTGCTCGCATCTCACCAACACACTTCGACAAATCTGGAGTCTCCCTGGTCCGTACGTCCAAAACCGTTTAAATGGGCGGGTGTGTCGTGAACCAATCTCCTCTTCCATTTGTCACATACTGGCGATGACATCCTTTTACTTGAATTATTCATCCGGGCACCAGCCGCTTTCCCTACGATCCCCGACACTCGGGGCTTCGGGAGTTGCCCGCCAAAAAACCGACAAACCAAACTATACAATCAATCCCATCTAGATGTAGGGGACTGAGGCTCTAAGCTATGCGCCTACTATACTTTGTAGGTATCAAACTACGCTTGAAGATAGTTGATAAGGAAGCGAATTGATCGAGTACCGTATCTTCAGTCCGACTCCCGTTCGAACGCAGCACGCTAACATGGTCCACTGGCATTCTTACTAAATACCTAGTTCACTTCTACATGAGGAGTGTCTGGGCCGGACTCACCTTTGATTAGATAACTGAAG
diff --git a/public/gwas-test/src/test/resources/fake_chrQ.fa.fai b/public/gwas-test/src/test/resources/fake_chrQ.fa.fai
new file mode 100644
index 0000000000000000000000000000000000000000..b7a558fdb3b3c0e85f6e3c634cc3ae80c601336d
--- /dev/null
+++ b/public/gwas-test/src/test/resources/fake_chrQ.fa.fai
@@ -0,0 +1 @@
+chrQ	16571	6	16571	16572
diff --git a/public/gwas-test/src/test/resources/log4j.properties b/public/gwas-test/src/test/resources/log4j.properties
new file mode 100644
index 0000000000000000000000000000000000000000..501af67582a546db584c8538b28cb6f9e07f1692
--- /dev/null
+++ b/public/gwas-test/src/test/resources/log4j.properties
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=ERROR, A1
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-5p [%d] [%C{1}] - %m%n
\ No newline at end of file
diff --git a/public/gwas-test/src/test/resources/specs/files.specs b/public/gwas-test/src/test/resources/specs/files.specs
new file mode 100644
index 0000000000000000000000000000000000000000..6385b4296366055c42ecf14e4d6443af7f8222b3
--- /dev/null
+++ b/public/gwas-test/src/test/resources/specs/files.specs
@@ -0,0 +1,26 @@
+{
+        files = (
+                {
+                        chromosome = "chrQ";
+                        name = "imputation_06/test";
+                        orig = "imputation_03/LLS_Offspring_Partners_Final_37_Overlap_chr1";
+                },
+                {
+                        chromosome = "chrQ";
+                        name = "imputation_06/test";
+                        orig = "imputation_03/LLS_Offspring_Partners_Final_37_Overlap_chr1";
+                },
+                {
+                        chromosome = "chrQ";
+                        name = "imputation_06/test";
+                        orig = "imputation_03/LLS_Offspring_Partners_Final_37_Overlap_chr22";
+                },
+                {
+                        chromosome = "chrQ";
+                        name = "imputation_06/test";
+                        orig = "imputation_03/LLS_Offspring_Partners_Final_37_Overlap_chr22";
+                }
+        );
+        jids = ( "2102064" );
+        type = "tped3col";
+}
\ No newline at end of file
diff --git a/public/gwas-test/src/test/resources/specs/test.gens b/public/gwas-test/src/test/resources/specs/test.gens
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/public/gwas-test/src/test/resources/specs/test.gens_info b/public/gwas-test/src/test/resources/specs/test.gens_info
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/public/gwas-test/src/test/resources/specs/test.gens_info_by_sample b/public/gwas-test/src/test/resources/specs/test.gens_info_by_sample
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/public/gwas-test/src/test/resources/specs/test.gens_summary b/public/gwas-test/src/test/resources/specs/test.gens_summary
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/public/gwas-test/src/test/resources/specs/test.gens_warnings b/public/gwas-test/src/test/resources/specs/test.gens_warnings
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/public/gwas-test/src/test/scala/nl/lumc/sasc/biopet/pipelines/gwastest/GwasTestTest.scala b/public/gwas-test/src/test/scala/nl/lumc/sasc/biopet/pipelines/gwastest/GwasTestTest.scala
new file mode 100644
index 0000000000000000000000000000000000000000..7455c60183fd9cffc0d6ebc4d44b7503b1a24d49
--- /dev/null
+++ b/public/gwas-test/src/test/scala/nl/lumc/sasc/biopet/pipelines/gwastest/GwasTestTest.scala
@@ -0,0 +1,98 @@
+package nl.lumc.sasc.biopet.pipelines.gwastest
+
+import java.io.File
+import java.nio.file.Paths
+
+import com.google.common.io.Files
+import nl.lumc.sasc.biopet.utils.config.Config
+import org.broadinstitute.gatk.queue.QSettings
+import org.scalatest.Matchers
+import org.scalatest.testng.TestNGSuite
+import org.testng.annotations.Test
+
+/**
+ * Created by pjvan_thof on 4/11/16.
+ */
+class GwasTestTest extends TestNGSuite with Matchers {
+  def initPipeline(map: Map[String, Any]): GwasTest = {
+    new GwasTest {
+      override def configNamespace = "gwastest"
+      override def globalConfig = new Config(map)
+      qSettings = new QSettings
+      qSettings.runName = "test"
+    }
+  }
+
+  @Test
+  def testFromVcf: Unit = {
+    val pipeline = initPipeline(GwasTestTest.config ++
+      Map("input_vcf" -> GwasTestTest.vcfFile.toString
+      )
+    )
+    pipeline.script()
+  }
+
+  @Test
+  def testFromGens: Unit = {
+    val pipeline = initPipeline(GwasTestTest.config ++
+      Map("input_gens" -> List(Map("genotypes" -> GwasTestTest.vcfFile, "contig" -> "chrQ"))
+      )
+    )
+    pipeline.script()
+  }
+
+  @Test
+  def testWrongContig: Unit = {
+    val pipeline = initPipeline(GwasTestTest.config ++
+      Map("input_gens" -> List(Map("genotypes" -> GwasTestTest.vcfFile, "contig" -> "chrBla"))
+      )
+    )
+    intercept[IllegalStateException] {
+      pipeline.script()
+    }
+  }
+
+  @Test
+  def testFromSpecs: Unit = {
+    val pipeline = initPipeline(GwasTestTest.config ++
+      Map("imute_specs_file" -> GwasTestTest.resourcePath("/specs/files.specs"))
+    )
+    pipeline.script()
+  }
+
+  @Test
+  def testEmpty: Unit = {
+    val pipeline = initPipeline(GwasTestTest.config)
+    intercept[IllegalArgumentException] {
+      pipeline.script()
+    }
+  }
+}
+
+object GwasTestTest {
+  val vcfFile = File.createTempFile("gwas.", ".vcf")
+  Files.touch(vcfFile)
+  vcfFile.deleteOnExit()
+
+  val phenotypeFile = File.createTempFile("gwas.", ".txt")
+  phenotypeFile.deleteOnExit()
+
+  val outputDir = Files.createTempDir()
+  outputDir.deleteOnExit()
+
+  val reference = new File(resourcePath("/fake_chrQ.fa"))
+
+  private def resourcePath(p: String): String = {
+    Paths.get(getClass.getResource(p).toURI).toString
+  }
+
+  val config = Map(
+    "reference_fasta" -> GwasTestTest.reference.toString,
+    "phenotype_file" -> GwasTestTest.phenotypeFile.toString,
+    "output_dir" -> outputDir,
+    "snptest" -> Map("exe" -> "test"),
+    "md5sum" -> Map("exe" -> "test"),
+    "gatk_jar" -> "test"
+  )
+
+}
diff --git a/public/pom.xml b/public/pom.xml
index 4171089d31ef05ec2c544c29154b809638004dd5..63bde77e79b63f61366f06a7d472a98b0cd9db0d 100644
--- a/public/pom.xml
+++ b/public/pom.xml
@@ -46,6 +46,7 @@
         <module>biopet-tools-extensions</module>
         <module>biopet-extensions</module>
         <module>biopet-tools-package</module>
+        <module>gwas-test</module>
     </modules>
 
     <properties>