Commit e5bbde4d authored by Ruben Vorderman's avatar Ruben Vorderman
Browse files

Formatted scala files with scalafmt

parent 1e95dc46
......@@ -17,7 +17,7 @@ package nl.lumc.sasc.biopet.pipelines.bamtobigwig
import java.io.File
import nl.lumc.sasc.biopet.utils.config.Configurable
import nl.lumc.sasc.biopet.core.{ BiopetQScript, PipelineCommand }
import nl.lumc.sasc.biopet.core.{BiopetQScript, PipelineCommand}
import nl.lumc.sasc.biopet.extensions.WigToBigWig
import nl.lumc.sasc.biopet.extensions.igvtools.IGVToolsCount
import org.broadinstitute.gatk.queue.QScript
......
......@@ -14,12 +14,12 @@
*/
package nl.lumc.sasc.biopet.pipelines.bamtobigwig
import java.io.{ File, PrintWriter }
import java.io.{File, PrintWriter}
import htsjdk.samtools.SamReaderFactory
import nl.lumc.sasc.biopet.utils.config.Configurable
import org.broadinstitute.gatk.queue.function.InProcessFunction
import org.broadinstitute.gatk.utils.commandline.{ Input, Output }
import org.broadinstitute.gatk.utils.commandline.{Input, Output}
import scala.collection.JavaConversions._
......
......@@ -39,6 +39,7 @@ class BamToChromSizesTest extends TestNGSuite with Matchers {
bamToChromSizes.chromSizesFile = File.createTempFile("chrom.", ".sizes")
bamToChromSizes.chromSizesFile.deleteOnExit()
bamToChromSizes.run()
Source.fromFile(bamToChromSizes.chromSizesFile).getLines().toList shouldBe List("chrQ\t10000", "chrR\t10000")
Source.fromFile(bamToChromSizes.chromSizesFile).getLines().toList shouldBe List("chrQ\t10000",
"chrR\t10000")
}
}
......@@ -16,19 +16,20 @@ package nl.lumc.sasc.biopet.pipelines.bammetrics
import java.io.File
import nl.lumc.sasc.biopet.core.annotations.{ AnnotationRefFlat, RibosomalRefFlat }
import nl.lumc.sasc.biopet.core.annotations.{AnnotationRefFlat, RibosomalRefFlat}
import nl.lumc.sasc.biopet.core.summary.SummaryQScript
import nl.lumc.sasc.biopet.core.{ BiopetFifoPipe, PipelineCommand, Reference, SampleLibraryTag }
import nl.lumc.sasc.biopet.extensions.bedtools.{ BedtoolsCoverage, BedtoolsIntersect, BedtoolsSort }
import nl.lumc.sasc.biopet.core.{BiopetFifoPipe, PipelineCommand, Reference, SampleLibraryTag}
import nl.lumc.sasc.biopet.extensions.bedtools.{BedtoolsCoverage, BedtoolsIntersect, BedtoolsSort}
import nl.lumc.sasc.biopet.extensions.picard._
import nl.lumc.sasc.biopet.extensions.samtools.SamtoolsFlagstat
import nl.lumc.sasc.biopet.extensions.tools.{ BamStats, BiopetFlagstat }
import nl.lumc.sasc.biopet.extensions.tools.{BamStats, BiopetFlagstat}
import nl.lumc.sasc.biopet.pipelines.bammetrics.scripts.CoverageStats
import nl.lumc.sasc.biopet.utils.config.Configurable
import nl.lumc.sasc.biopet.utils.intervals.BedCheck
import org.broadinstitute.gatk.queue.QScript
class BamMetrics(val parent: Configurable) extends QScript
class BamMetrics(val parent: Configurable)
extends QScript
with SummaryQScript
with SampleLibraryTag
with Reference
......@@ -44,22 +45,23 @@ class BamMetrics(val parent: Configurable) extends QScript
override def defaults = Map("bedtoolscoverage" -> Map("sorted" -> true))
/** returns files to store in summary */
def summaryFiles = Map("reference" -> referenceFasta(),
"input_bam" -> inputBam) ++
def summaryFiles =
Map("reference" -> referenceFasta(), "input_bam" -> inputBam) ++
ampliconBedFile.map("amplicon" -> _).toMap ++
ampliconBedFile.map(x => "roi_" + x.getName.stripSuffix(".bed") -> x).toMap
/** return settings */
def summarySettings = Map("amplicon_name" -> ampliconBedFile.collect { case x => x.getName.stripSuffix(".bed") },
def summarySettings =
Map("amplicon_name" -> ampliconBedFile.collect { case x => x.getName.stripSuffix(".bed") },
"roi_name" -> roiBedFiles.map(_.getName.stripSuffix(".bed")))
override def reportClass = {
val bammetricsReport = new BammetricsReport(this)
bammetricsReport.outputDir = new File(outputDir, "report")
bammetricsReport.summaryDbFile = summaryDbFile
bammetricsReport.args = if (libId.isDefined) Map(
"sampleId" -> sampleId.getOrElse("."),
"libId" -> libId.getOrElse("."))
bammetricsReport.args =
if (libId.isDefined)
Map("sampleId" -> sampleId.getOrElse("."), "libId" -> libId.getOrElse("."))
else Map("sampleId" -> sampleId.getOrElse("."))
Some(bammetricsReport)
}
......@@ -67,7 +69,8 @@ class BamMetrics(val parent: Configurable) extends QScript
/** executed before script */
def init(): Unit = {
inputFiles :+= new InputFile(inputBam)
ampliconBedFile.foreach(BedCheck.checkBedFileToReference(_, referenceFasta(), biopetError = true))
ampliconBedFile.foreach(
BedCheck.checkBedFileToReference(_, referenceFasta(), biopetError = true))
roiBedFiles.foreach(BedCheck.checkBedFileToReference(_, referenceFasta(), biopetError = true))
}
......@@ -129,13 +132,19 @@ class BamMetrics(val parent: Configurable) extends QScript
ampBedToInterval.isIntermediate = true
add(ampBedToInterval)
val chsMetrics = CollectHsMetrics(this, inputBam,
List(ampIntervals), ampIntervals :: roiIntervals.map(_.intervals), outputDir)
val chsMetrics = CollectHsMetrics(this,
inputBam,
List(ampIntervals),
ampIntervals :: roiIntervals.map(_.intervals),
outputDir)
add(chsMetrics)
addSummarizable(chsMetrics, "hs_metrics")
val pcrMetrics = CollectTargetedPcrMetrics(this, inputBam,
ampIntervals, ampIntervals :: roiIntervals.map(_.intervals), outputDir)
val pcrMetrics = CollectTargetedPcrMetrics(this,
inputBam,
ampIntervals,
ampIntervals :: roiIntervals.map(_.intervals),
outputDir)
add(pcrMetrics)
addSummarizable(pcrMetrics, "targeted_pcr_metrics")
......@@ -145,36 +154,48 @@ class BamMetrics(val parent: Configurable) extends QScript
// Create stats and coverage plot for each bed/interval file
val allIntervalNames = (roiIntervals ++ ampIntervals).map(_.bed.getName)
if (allIntervalNames.size != allIntervalNames.toSet.size) {
logger.warn("There are multiple region files with the same name. Metric values might get overwritten")
logger.warn(
"There are multiple region files with the same name. Metric values might get overwritten")
}
for (intervals <- roiIntervals ++ ampIntervals) {
val targetName = intervals.bed.getName.stripSuffix(".bed")
val targetDir = new File(outputDir, targetName)
val biStrict = BedtoolsIntersect(this, inputBam, intervals.bed,
val biStrict = BedtoolsIntersect(
this,
inputBam,
intervals.bed,
output = new File(targetDir, inputBam.getName.stripSuffix(".bam") + ".overlap.strict.sam"),
minOverlap = config("strict_intersect_overlap", default = 1.0))
minOverlap = config("strict_intersect_overlap", default = 1.0)
)
val biopetFlagstatStrict = BiopetFlagstat(this, biStrict.output, targetDir)
addSummarizable(biopetFlagstatStrict, targetName + "_flagstats_strict")
add(new BiopetFifoPipe(this, List(biStrict, biopetFlagstatStrict)))
val biLoose = BedtoolsIntersect(this, inputBam, intervals.bed,
val biLoose = BedtoolsIntersect(
this,
inputBam,
intervals.bed,
output = new File(targetDir, inputBam.getName.stripSuffix(".bam") + ".overlap.loose.sam"),
minOverlap = config("loose_intersect_overlap", default = 0.01))
minOverlap = config("loose_intersect_overlap", default = 0.01)
)
val biopetFlagstatLoose = BiopetFlagstat(this, biLoose.output, targetDir)
addSummarizable(biopetFlagstatLoose, targetName + "_flagstats_loose")
add(new BiopetFifoPipe(this, List(biLoose, biopetFlagstatLoose)))
val sortedBed = BamMetrics.sortedbedCache.getOrElse(intervals.bed, {
val sortedBed = BamMetrics.sortedbedCache.getOrElse(
intervals.bed, {
val sorter = new BedtoolsSort(this)
sorter.input = intervals.bed
sorter.output = swapExt(targetDir, intervals.bed, ".bed", ".sorted.bed")
add(sorter)
BamMetrics.sortedbedCache += intervals.bed -> sorter.output
sorter.output
})
}
)
val bedCov = BedtoolsCoverage(this, sortedBed, inputBam, depth = true)
val covStats = CoverageStats(this, targetDir, inputBam.getName.stripSuffix(".bam") + ".coverage")
val covStats =
CoverageStats(this, targetDir, inputBam.getName.stripSuffix(".bam") + ".coverage")
covStats.title = Some("Coverage Plot")
covStats.subTitle = Some(s"for file '$targetName.bed'")
add(bedCov | covStats)
......@@ -186,9 +207,11 @@ class BamMetrics(val parent: Configurable) extends QScript
}
object BamMetrics extends PipelineCommand {
/** Make default implementation of BamMetrics and runs script already */
def apply(root: Configurable,
bamFile: File, outputDir: File,
bamFile: File,
outputDir: File,
sampleId: Option[String] = None,
libId: Option[String] = None): BamMetrics = {
val bamMetrics = new BamMetrics(root)
......
......@@ -14,17 +14,22 @@
*/
package nl.lumc.sasc.biopet.pipelines.bammetrics
import java.io.{ File, PrintWriter }
import java.io.{File, PrintWriter}
import nl.lumc.sasc.biopet.utils.config.Configurable
import nl.lumc.sasc.biopet.core.report.{ ReportBuilder, ReportBuilderExtension, ReportPage, ReportSection }
import nl.lumc.sasc.biopet.core.report.{
ReportBuilder,
ReportBuilderExtension,
ReportPage,
ReportSection
}
import nl.lumc.sasc.biopet.utils.ConfigUtils
import nl.lumc.sasc.biopet.utils.rscript.{ LinePlot, StackedBarPlot }
import nl.lumc.sasc.biopet.utils.rscript.{LinePlot, StackedBarPlot}
import nl.lumc.sasc.biopet.utils.summary.db.SummaryDb
import nl.lumc.sasc.biopet.utils.summary.db.SummaryDb.Implicts._
import nl.lumc.sasc.biopet.utils.summary.db.SummaryDb._
import scala.concurrent.{ Await, Future }
import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration
class BammetricsReport(val parent: Configurable) extends ReportBuilderExtension {
......@@ -46,12 +51,18 @@ object BammetricsReport extends ReportBuilder {
/** Root page for single BamMetrcis report */
def indexPage: Future[ReportPage] =
bamMetricsPage(summary, sampleId, libId).map { bamMetricsPage =>
ReportPage(bamMetricsPage.subPages ::: List(
"Versions" -> Future(ReportPage(List(), List("Executables" -> ReportSection("/nl/lumc/sasc/biopet/core/report/executables.ssp"
)), Map())),
ReportPage(
bamMetricsPage.subPages ::: List(
"Versions" -> Future(
ReportPage(List(),
List("Executables" -> ReportSection(
"/nl/lumc/sasc/biopet/core/report/executables.ssp")),
Map())),
"Files" -> filesPage(sampleId, libId)
), List(
"Report" -> ReportSection("/nl/lumc/sasc/biopet/pipelines/bammetrics/bamMetricsFront.ssp")
),
List(
"Report" -> ReportSection(
"/nl/lumc/sasc/biopet/pipelines/bammetrics/bamMetricsFront.ssp")
) ::: bamMetricsPage.sections,
Map()
)
......@@ -62,16 +73,36 @@ object BammetricsReport extends ReportBuilder {
sampleId: Option[Int],
libId: Option[Int],
metricsTag: String = "bammetrics"): Future[ReportPage] = Future {
val wgsExecuted = summary.getStatsSize(runId, metricsTag, "wgs", sample = sampleId.map(SampleId), library = libId.map(LibraryId)) >= 1
val rnaExecuted = summary.getStatsSize(runId, metricsTag, "rna", sample = sampleId.map(SampleId), library = libId.map(LibraryId)) >= 1
val insertsizeMetrics = summary.getStatKeys(runId, metricsTag, "CollectInsertSizeMetrics",
sampleId.map(SampleId).getOrElse(NoSample), libId.map(LibraryId).getOrElse(NoLibrary), Map("metrics" -> List("metrics")))
val wgsExecuted = summary.getStatsSize(runId,
metricsTag,
"wgs",
sample = sampleId.map(SampleId),
library = libId.map(LibraryId)) >= 1
val rnaExecuted = summary.getStatsSize(runId,
metricsTag,
"rna",
sample = sampleId.map(SampleId),
library = libId.map(LibraryId)) >= 1
val insertsizeMetrics = summary
.getStatKeys(
runId,
metricsTag,
"CollectInsertSizeMetrics",
sampleId.map(SampleId).getOrElse(NoSample),
libId.map(LibraryId).getOrElse(NoLibrary),
Map("metrics" -> List("metrics"))
)
.exists(_._2.isDefined)
val targetSettings = summary.getSettingKeys(runId, metricsTag, NoModule,
sample = sampleId.map(SampleId).getOrElse(NoSample), library = libId.map(LibraryId).getOrElse(NoLibrary),
Map("amplicon_name" -> List("amplicon_name"), "roi_name" -> List("roi_name")))
val targetSettings = summary.getSettingKeys(
runId,
metricsTag,
NoModule,
sample = sampleId.map(SampleId).getOrElse(NoSample),
library = libId.map(LibraryId).getOrElse(NoLibrary),
Map("amplicon_name" -> List("amplicon_name"), "roi_name" -> List("roi_name"))
)
val targets = (
targetSettings("amplicon_name"),
targetSettings("roi_name")
......@@ -83,20 +114,39 @@ object BammetricsReport extends ReportBuilder {
ReportPage(
if (targets.isEmpty) List()
else List("Targets" -> Future.successful(ReportPage(
else
List(
"Targets" -> Future.successful(
ReportPage(
List(),
targets.map(t => t -> ReportSection("/nl/lumc/sasc/biopet/pipelines/bammetrics/covstatsPlot.ssp", Map("target" -> Some(t)))),
targets.map(t =>
t -> ReportSection("/nl/lumc/sasc/biopet/pipelines/bammetrics/covstatsPlot.ssp",
Map("target" -> Some(t)))),
Map()))),
List(
"Summary" -> ReportSection("/nl/lumc/sasc/biopet/pipelines/bammetrics/alignmentSummary.ssp"),
"Mapping Quality" -> ReportSection("/nl/lumc/sasc/biopet/pipelines/bammetrics/mappingQuality.ssp", Map("showPlot" -> true)),
"Clipping" -> ReportSection("/nl/lumc/sasc/biopet/pipelines/bammetrics/clipping.ssp", Map("showPlot" -> true))) ++
(if (insertsizeMetrics) List("Insert Size" -> ReportSection("/nl/lumc/sasc/biopet/pipelines/bammetrics/insertSize.ssp", Map("showPlot" -> true))
)
else Nil) ++ (if (wgsExecuted) List("Whole genome coverage" -> ReportSection("/nl/lumc/sasc/biopet/pipelines/bammetrics/wgsHistogram.ssp",
"Summary" -> ReportSection(
"/nl/lumc/sasc/biopet/pipelines/bammetrics/alignmentSummary.ssp"),
"Mapping Quality" -> ReportSection(
"/nl/lumc/sasc/biopet/pipelines/bammetrics/mappingQuality.ssp",
Map("showPlot" -> true)),
"Clipping" -> ReportSection("/nl/lumc/sasc/biopet/pipelines/bammetrics/clipping.ssp",
Map("showPlot" -> true))
) ++
(if (insertsizeMetrics)
List(
"Insert Size" -> ReportSection(
"/nl/lumc/sasc/biopet/pipelines/bammetrics/insertSize.ssp",
Map("showPlot" -> true)))
else Nil) ++ (if (wgsExecuted)
List(
"Whole genome coverage" -> ReportSection(
"/nl/lumc/sasc/biopet/pipelines/bammetrics/wgsHistogram.ssp",
Map("showPlot" -> true)))
else Nil) ++
(if (rnaExecuted) List("Rna coverage" -> ReportSection("/nl/lumc/sasc/biopet/pipelines/bammetrics/rnaHistogram.ssp",
(if (rnaExecuted)
List(
"Rna coverage" -> ReportSection(
"/nl/lumc/sasc/biopet/pipelines/bammetrics/rnaHistogram.ssp",
Map("showPlot" -> true)))
else Nil),
Map("metricsTag" -> metricsTag)
......@@ -131,16 +181,29 @@ object BammetricsReport extends ReportBuilder {
)
val results: Map[(Int, Option[Int]), Map[String, Option[Any]]] = if (libraryLevel) {
summary.getStatsForLibraries(runId, "bammetrics", "bamstats",
sampleId = sampleId, keyValues = statsPaths).map(x => (x._1._1, Some(x._1._2)) -> x._2)
} else summary.getStatsForSamples(runId, "bammetrics", "bamstats",
sample = sampleId.map(SampleId), keyValues = statsPaths).map(x => (x._1, None) -> x._2)
summary
.getStatsForLibraries(runId,
"bammetrics",
"bamstats",
sampleId = sampleId,
keyValues = statsPaths)
.map(x => (x._1._1, Some(x._1._2)) -> x._2)
} else
summary
.getStatsForSamples(runId,
"bammetrics",
"bamstats",
sample = sampleId.map(SampleId),
keyValues = statsPaths)
.map(x => (x._1, None) -> x._2)
for (((s, l), result) <- results) {
val sampleName: String = summary.getSampleName(s).map(_.get)
val libName: Option[String] = l.flatMap(x => Await.result(summary.getLibraryName(x), Duration.Inf))
val libName: Option[String] =
l.flatMap(x => Await.result(summary.getLibraryName(x), Duration.Inf))
val sb = new StringBuffer()
if (libName.isDefined) sb.append(sampleName + "-" + libName.get + "\t") else sb.append(sampleName + "\t")
if (libName.isDefined) sb.append(sampleName + "-" + libName.get + "\t")
else sb.append(sampleName + "\t")
val mapped = ConfigUtils.any2long(result("Mapped"))
val duplicates = ConfigUtils.any2long(result("Duplicates"))
val total = ConfigUtils.any2long(result("All"))
......@@ -182,16 +245,27 @@ object BammetricsReport extends ReportBuilder {
val pngFile = new File(outputDir, prefix + ".png")
val results: Map[(Int, Option[Int]), Map[String, Option[Array[Any]]]] = if (libraryLevel) {
summary.getStatsForLibraries(runId, pipeline, module, sampleId = sampleId, keyValues = statsPaths)
.map(x => (x._1._1, Some(x._1._2)) -> x._2.map(x => x._1 -> x._2.map(ConfigUtils.any2list(_).toArray)))
} else summary.getStatsForSamples(runId, pipeline, module, sample = sampleId.map(SampleId), keyValues = statsPaths)
summary
.getStatsForLibraries(runId, pipeline, module, sampleId = sampleId, keyValues = statsPaths)
.map(x =>
(x._1._1, Some(x._1._2)) -> x._2.map(x =>
x._1 -> x._2.map(ConfigUtils.any2list(_).toArray)))
} else
summary
.getStatsForSamples(runId,
pipeline,
module,
sample = sampleId.map(SampleId),
keyValues = statsPaths)
.map(x => (x._1, None) -> x._2.map(x => x._1 -> x._2.map(ConfigUtils.any2list(_).toArray)))
val tables: Array[Map[String, Array[Any]]] = results.map {
case ((sample, library), map) =>
val sampleName = Await.result(summary.getSampleName(sample), Duration.Inf)
val sampleName = Await
.result(summary.getSampleName(sample), Duration.Inf)
.getOrElse(throw new IllegalStateException("Sample must be there"))
val libraryName = library.flatMap(l => Await.result(summary.getLibraryName(l), Duration.Inf))
val libraryName =
library.flatMap(l => Await.result(summary.getLibraryName(l), Duration.Inf))
Map(
yKey -> map(yKey).getOrElse(Array()),
(sampleName + libraryName.map("-" + _).getOrElse("")) -> map(xKey).getOrElse(Array())
......@@ -200,7 +274,8 @@ object BammetricsReport extends ReportBuilder {
writeTableToTsv(tsvFile, mergeTables(tables, yKey), yKey)
LinePlot(tsvFile, pngFile,
LinePlot(tsvFile,
pngFile,
xlabel = xlabel,
ylabel = ylabel,
title = title,
......@@ -228,9 +303,22 @@ object BammetricsReport extends ReportBuilder {
"count" -> List("histogram", "All_Reads.fr_count")
)
writePlotFromSummary(outputDir, prefix, summary, libraryLevel, sampleId, libraryId, statsPaths,
"insert_size", "count", "bammetrics", "CollectInsertSizeMetrics",
"Insert size", "Reads", "Insert size")
writePlotFromSummary(
outputDir,
prefix,
summary,
libraryLevel,
sampleId,
libraryId,
statsPaths,
"insert_size",
"count",
"bammetrics",
"CollectInsertSizeMetrics",
"Insert size",
"Reads",
"Insert size"
)
}
def mappingQualityPlot(outputDir: File,
......@@ -244,9 +332,22 @@ object BammetricsReport extends ReportBuilder {
"count" -> List("mapping_quality", "histogram", "counts")
)
writePlotFromSummary(outputDir, prefix, summary, libraryLevel, sampleId, libraryId, statsPaths,
"mapping_quality", "count", "bammetrics", "bamstats",
"Mapping quality", "Reads", "Mapping quality")
writePlotFromSummary(
outputDir,
prefix,
summary,
libraryLevel,
sampleId,
libraryId,
statsPaths,
"mapping_quality",
"count",
"bammetrics",
"bamstats",
"Mapping quality",
"Reads",
"Mapping quality"
)
}
def clippingPlot(outputDir: File,
......@@ -260,9 +361,20 @@ object BammetricsReport extends ReportBuilder {
"count" -> List("clipping", "histogram", "counts")
)
writePlotFromSummary(outputDir, prefix, summary, libraryLevel, sampleId, libraryId, statsPaths,
"clipping", "count", "bammetrics", "bamstats",
"Clipping", "Reads", "Clipping")
writePlotFromSummary(outputDir,
prefix,
summary,
libraryLevel,
sampleId,
libraryId,
statsPaths,
"clipping",
"count",
"bammetrics",
"bamstats",
"Clipping",
"Reads",
"Clipping")
}
/**
......@@ -285,9 +397,20 @@ object BammetricsReport extends ReportBuilder {
"count" -> List("histogram", "count")
)
writePlotFromSummary(outputDir, prefix, summary, libraryLevel, sampleId, libraryId, statsPaths,
"coverage", "count", "bammetrics", "wgs",
"Coverage", "Bases", "Whole genome coverage")
writePlotFromSummary(outputDir,
prefix,
summary,
libraryLevel,
sampleId,
libraryId,
statsPaths,
"coverage",
"count",
"bammetrics",
"wgs",
"Coverage",
"Bases",
"Whole genome coverage")
}
/**
......@@ -310,21 +433,37 @@ object BammetricsReport extends ReportBuilder {
"count" -> List("histogram", "All_Reads.normalized_coverage")
)
writePlotFromSummary(outputDir, prefix, summary, libraryLevel, sampleId, libraryId, statsPaths,
"position", "count", "bammetrics", "rna",
"Relative position", "Coverage", "Rna coverage")
writePlotFromSummary(
outputDir,
prefix,
summary,
libraryLevel,
sampleId,
libraryId,
statsPaths,
"position",
"count",
"bammetrics",
"rna",
"Relative position",
"Coverage",
"Rna coverage"
)
}
def mergeTables(tables: Array[Map[String, Array[Any]]],
mergeColumn: String, defaultValue: Any = 0): Map[String, Array[Any]] = {
mergeColumn: String,
defaultValue: Any = 0): Map[String, Array[Any]] = {
val keys = tables.flatMap(x => x(mergeColumn)).distinct
(for (table <- tables; (columnKey, columnValues) <- table if columnKey != mergeColumn) yield {
columnKey -> keys.map(x => table(mergeColumn).zip(columnValues).toMap.getOrElse(x, defaultValue))
columnKey -> keys.map(x =>
table(mergeColumn).zip(columnValues).toMap.getOrElse(x, defaultValue))
}).toMap + (mergeColumn -> keys)
}
def writeTableToTsv(tsvFile: File, table: Map[String, Array[Any]], firstColumn: String): Unit = {
require(table.map(_._2.size).toList.distinct.size == 1, "Not all values has the same number or rows")