Commit b27102c7 authored by Peter van 't Hof's avatar Peter van 't Hof
Browse files

Try with Either class

parent d4d307a2
......@@ -14,12 +14,17 @@
*/
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.{ ReportBuilderExtension, ReportBuilder, ReportPage, ReportSection }
import nl.lumc.sasc.biopet.utils.summary.{ Summary, SummaryValue }
import nl.lumc.sasc.biopet.utils.rscript.{ StackedBarPlot, LinePlot }
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.summary.db.SummaryDb
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration.Duration
class BammetricsReport(val parent: Configurable) extends ReportBuilderExtension {
def builder = BammetricsReport
......@@ -52,23 +57,26 @@ object BammetricsReport extends ReportBuilder {
}
/** Generates a page with alignment stats */
def bamMetricsPage(summary: Summary,
sampleId: Option[String],
libId: Option[String],
def bamMetricsPage(summary: SummaryDb,
sampleId: Option[Int],
libId: Option[Int],
metricsTag: String = "bammetrics") = {
val wgsExecuted = summary.getValue(sampleId, libId, metricsTag, "stats", "wgs").isDefined
val rnaExecuted = summary.getValue(sampleId, libId, metricsTag, "stats", "rna").isDefined
//val pipelineId: Int = summary.getPipelineId(runId, metricsTag).map(_.get)
val insertsizeMetrics = summary.getValue(sampleId, libId, metricsTag, "stats", "CollectInsertSizeMetrics", "metrics") match {
case Some(None) => false
case Some(_) => true
case _ => false
}
val wgsExecuted = summary.getStatsSize(runId, Right(metricsTag), Some(Right("wgs")), sample = sampleId.map(Left(_)), library = libId.map(Left(_))) >= 1
val rnaExecuted = summary.getStatsSize(runId, Right(metricsTag), Some(Right("rna")), sample = sampleId.map(Left(_)), library = libId.map(Left(_))) >= 1
val insertsizeMetrics = summary.getStatKeys(runId, Right(metricsTag), Some(Right("CollectInsertSizeMetrics")),
sample = sampleId.map(Left(_)), library = libId.map(Left(_)), Map("metrics" -> List("metrics")))
.exists(_._2.isDefined)
val targetSettings = summary.getSettingKeys(runId, Right(metricsTag),None, sample = sampleId.map(Left(_)), library = libId.map(Left(_)),
Map("amplicon_name" -> List("amplicon_name"), "roi_name" -> List("roi_name")))
val targets = (
summary.getValue(sampleId, libId, metricsTag, "settings", "amplicon_name"),
summary.getValue(sampleId, libId, metricsTag, "settings", "roi_name")
targetSettings("amplicon_name"),
targetSettings("roi_name")
) match {
case (Some(amplicon: String), Some(roi: List[_])) => amplicon :: roi.map(_.toString)
case (_, Some(roi: List[_])) => roi.map(_.toString)
......@@ -108,44 +116,43 @@ object BammetricsReport extends ReportBuilder {
*/
def alignmentSummaryPlot(outputDir: File,
prefix: String,
summary: Summary,
summary: SummaryDb,
libraryLevel: Boolean = false,
sampleId: Option[String] = None): Unit = {
sampleId: Option[Int] = None): Unit = {
val tsvFile = new File(outputDir, prefix + ".tsv")
val pngFile = new File(outputDir, prefix + ".png")
val tsvWriter = new PrintWriter(tsvFile)
if (libraryLevel) tsvWriter.print("Library") else tsvWriter.print("Sample")
tsvWriter.println("\tMapped\tDuplicates\tUnmapped\tSecondary")
def getLine(summary: Summary, sample: String, lib: Option[String] = None): String = {
val mapped = new SummaryValue(List("bammetrics", "stats", "bamstats", "flagstats", "Mapped"),
summary, Some(sample), lib).value.getOrElse(0).toString.toLong
val duplicates = new SummaryValue(List("bammetrics", "stats", "bamstats", "flagstats", "Duplicates"),
summary, Some(sample), lib).value.getOrElse(0).toString.toLong
val total = new SummaryValue(List("bammetrics", "stats", "bamstats", "flagstats", "All"),
summary, Some(sample), lib).value.getOrElse(0).toString.toLong
val secondary = new SummaryValue(List("bammetrics", "stats", "bamstats", "flagstats", "NotPrimaryAlignment"),
summary, Some(sample), lib).value.getOrElse(0).toString.toLong
val statsPaths = Map(
"Mapped" -> List("flagstats", "Mapped"),
"Duplicates" -> List("flagstats", "Duplicates"),
"All" -> List("flagstats", "All"),
"NotPrimaryAlignment" -> List("flagstats", "NotPrimaryAlignment")
)
val pipelineId: Int = summary.getPipelineId(runId, "bammetrics").map(_.get)
val moduleId: Option[Int] = summary.getmoduleId(runId, "bamstats", pipelineId)
val results: Map[(Int, Option[Int]), Map[String, Option[Any]]] = if (libraryLevel) {
summary.getStatsForLibraries(runId = runId, pipelineName = "bammetrics", moduleName = Some("bamstats"), sampleId = sampleId, keyValues = statsPaths).map(x => (x._1._1, Some(x._1._2)) -> x._2)
} else summary.getStatsForSamples(runId, pipelineId, moduleId, sample = 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 sb = new StringBuffer()
if (lib.isDefined) sb.append(sample + "-" + lib.get + "\t") else sb.append(sample + "\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"))
val secondary = ConfigUtils.any2long(result("NotPrimaryAlignment"))
sb.append((mapped - duplicates - secondary) + "\t")
sb.append(duplicates + "\t")
sb.append((total - mapped) + "\t")
sb.append(secondary)
sb.toString
}
if (libraryLevel) {
for (
sample <- summary.samples if sampleId.isEmpty || sample == sampleId.get;
lib <- summary.libraries(sample)
) {
tsvWriter.println(getLine(summary, sample, Some(lib)))
}
} else {
for (sample <- summary.samples if sampleId.isEmpty || sample == sampleId.get) {
tsvWriter.println(getLine(summary, sample))
}
tsvWriter.println(sb.toString)
}
tsvWriter.close()
......@@ -155,8 +162,8 @@ object BammetricsReport extends ReportBuilder {
plot.output = pngFile
plot.ylabel = Some("Reads")
if (libraryLevel) {
plot.width = Some(200 + (summary.libraries.filter(s => sampleId.getOrElse(s._1) == s._1).foldLeft(0)(_ + _._2.size) * 10))
} else plot.width = Some(200 + (summary.samples.count(s => sampleId.getOrElse(s) == s) * 10))
plot.width = Some(200 + (libraries.filter(s => sampleId.getOrElse(s.id) == s.id).size) * 10)
} else plot.width = Some(200 + (samples.count(s => sampleId.getOrElse(s) == s) * 10))
plot.title = Some("Aligned reads")
plot.runLocal()
}
......@@ -172,18 +179,27 @@ object BammetricsReport extends ReportBuilder {
*/
def insertSizePlot(outputDir: File,
prefix: String,
summary: Summary,
summary: SummaryDb,
libraryLevel: Boolean = false,
sampleId: Option[String] = None,
libId: Option[String] = None): Unit = {
sampleId: Option[Int] = None,
libId: Option[Int] = None): Unit = {
val tsvFile = new File(outputDir, prefix + ".tsv")
val pngFile = new File(outputDir, prefix + ".png")
def paths(name: String) = Map(
"insert_size" -> List("bammetrics", "stats", "CollectInsertSizeMetrics", "histogram", "insert_size"),
name -> List("bammetrics", "stats", "CollectInsertSizeMetrics", "histogram", "All_Reads.fr_count")
val statsPaths = Map(
"insert_size" -> List("histogram", "insert_size"),
"All_Reads.fr_count" -> List("histogram", "All_Reads.fr_count")
)
val pipelineId: Int = summary.getPipelineId(runId, "bammetrics").map(_.get)
val moduleId: Option[Int] = summary.getmoduleId(runId, "CollectInsertSizeMetrics", pipelineId)
val results: Map[(Int, Option[Int]), Map[String, Option[Array[Any]]]] = if (libraryLevel) {
summary.getStatsForLibraries(runId, pipelineId, moduleId, 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, pipelineId, moduleId, sample = sampleId, keyValues = statsPaths)
.map(x => (x._1, None) -> x._2.map(x => x._1 -> x._2.map(ConfigUtils.any2list(_).toArray)))
val tables = getSampleLibraries(summary, sampleId, libId, libraryLevel)
.map {
case (sample, lib) =>
......@@ -200,10 +216,10 @@ object BammetricsReport extends ReportBuilder {
def mappingQualityPlot(outputDir: File,
prefix: String,
summary: Summary,
summary: SummaryDb,
libraryLevel: Boolean = false,
sampleId: Option[String] = None,
libId: Option[String] = None): Unit = {
sampleId: Option[Int] = None,
libId: Option[Int] = None): Unit = {
val tsvFile = new File(outputDir, prefix + ".tsv")
val pngFile = new File(outputDir, prefix + ".png")
......@@ -228,10 +244,10 @@ object BammetricsReport extends ReportBuilder {
def clippingPlot(outputDir: File,
prefix: String,
summary: Summary,
summary: SummaryDb,
libraryLevel: Boolean = false,
sampleId: Option[String] = None,
libId: Option[String] = None): Unit = {
sampleId: Option[Int] = None,
libId: Option[Int] = None): Unit = {
val tsvFile = new File(outputDir, prefix + ".tsv")
val pngFile = new File(outputDir, prefix + ".png")
......@@ -265,10 +281,10 @@ object BammetricsReport extends ReportBuilder {
*/
def wgsHistogramPlot(outputDir: File,
prefix: String,
summary: Summary,
summary: SummaryDb,
libraryLevel: Boolean = false,
sampleId: Option[String] = None,
libId: Option[String] = None): Unit = {
sampleId: Option[Int] = None,
libId: Option[Int] = None): Unit = {
val tsvFile = new File(outputDir, prefix + ".tsv")
val pngFile = new File(outputDir, prefix + ".png")
......@@ -302,7 +318,7 @@ object BammetricsReport extends ReportBuilder {
*/
def rnaHistogramPlot(outputDir: File,
prefix: String,
summary: Summary,
summary: SummaryDb,
libraryLevel: Boolean = false,
sampleId: Option[String] = None,
libId: Option[String] = None): Unit = {
......@@ -328,20 +344,20 @@ object BammetricsReport extends ReportBuilder {
removeZero = true).runLocal()
}
private def getSampleLibraries(summary: Summary,
sampleId: Option[String] = None,
LibId: Option[String] = None,
libraryLevel: Boolean = false): List[(String, Option[String])] = {
private def getSampleLibraries(summary: SummaryDb,
sampleId: Option[Int] = None,
LibId: Option[Int] = None,
libraryLevel: Boolean = false): List[(Int, Option[Int])] = {
if (LibId.isDefined) require(sampleId.isDefined)
if (libraryLevel || LibId.isDefined)
for ((sample, libs) <- summary.libraries.toList; lib <- libs) yield (sample, Some(lib))
else for ((sample, libs) <- summary.libraries.toList) yield (sample, None)
}
def getTableFromSummary(summary: Summary,
def getTableFromSummary(summary: SummaryDb,
paths: Map[String, List[String]],
sampleId: Option[String] = None,
libId: Option[String] = None): Map[String, Array[Any]] = {
sampleId: Option[Int] = None,
libId: Option[Int] = None): Map[String, Array[Any]] = {
val pathValues: Map[String, Array[Any]] = paths.map {
case (key, path) =>
val value = summary.getValueAsArray(sampleId, libId, path: _*)
......
......@@ -17,13 +17,15 @@ package nl.lumc.sasc.biopet.core.report
import java.io._
import nl.lumc.sasc.biopet.core.ToolCommandFunction
import nl.lumc.sasc.biopet.utils.summary.db.Schema.{Library, Sample}
import nl.lumc.sasc.biopet.utils.summary.db.SummaryDb
import nl.lumc.sasc.biopet.utils.{IoUtils, Logging, ToolCommand}
import org.broadinstitute.gatk.utils.commandline.Input
import nl.lumc.sasc.biopet.utils.tryToParseNumber
import org.fusesource.scalate.{TemplateEngine, TemplateSource}
import scala.collection.mutable
import scala.concurrent.Await
import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration
import scala.language.postfixOps
......@@ -72,6 +74,7 @@ trait ReportBuilderExtension extends ToolCommandFunction {
trait ReportBuilder extends ToolCommand {
implicit def toOption[T](x: T) : Option[T] = Option(x)
implicit def autoWait[T](x: Future[T]) : T = Await.result(x, Duration.Inf)
case class Args(summaryDbFile: File = null,
outputDir: File = null,
......@@ -115,21 +118,10 @@ trait ReportBuilder extends ToolCommand {
final def runId = setRunId
private var setSampleCache: Map[String, Int] = _
final def sampleCache = setSampleCache
private var setLibraryCache: Map[(String, String), Int] = _
final def libraryCache = setSampleCache
private var setPipelineCache: Map[String, Int] = _
final def pipelineCache = setPipelineCache
private var setModuleCache: Map[String, Int] = _
final def moduleCache = setModuleCache
private var _setSamples = Seq[Sample]()
final def samples = _setSamples
private var _setLibraries = Seq[Library]()
final def libraries = _setLibraries
/** default args that are passed to all page withing the report */
def pageArgs: Map[String, Any] = Map()
......@@ -137,9 +129,9 @@ trait ReportBuilder extends ToolCommand {
private var done = 0
private var total = 0
private var _sampleId: Option[String] = None
private var _sampleId: Option[Int] = None
protected[report] def sampleId = _sampleId
private var _libId: Option[String] = None
private var _libId: Option[Int] = None
protected[report] def libId = _libId
case class ExtFile(resourcePath: String, targetPath: String)
......@@ -168,20 +160,26 @@ trait ReportBuilder extends ToolCommand {
require(cmdArgs.outputDir.exists(), "Output dir does not exist")
require(cmdArgs.outputDir.isDirectory, "Output dir is not a directory")
setSummary = SummaryDb.openSqliteSummary(cmdArgs.summaryDbFile)
setRunId = cmdArgs.runId
cmdArgs.pageArgs.get("sampleId") match {
case Some(s: String) =>
cmdArgs.pageArgs += "sampleId" -> Some(s)
_sampleId = Some(s)
_sampleId = Await.result(summary.getSampleId(runId, s), Duration.Inf)
cmdArgs.pageArgs += "sampleId" -> sampleId
case _ =>
}
cmdArgs.pageArgs.get("libId") match {
case Some(l: String) =>
cmdArgs.pageArgs += "libId" -> Some(l)
_libId = Some(l)
_libId = Await.result(summary.getLibraryId(runId, sampleId.get, l), Duration.Inf)
cmdArgs.pageArgs += "libId" -> libId
case _ =>
}
_setSamples = Await.result(summary.getSamples(runId = Some(runId), sampleId = sampleId), Duration.Inf)
_setLibraries = Await.result(summary.getLibraries(runId = Some(runId), sampleId = sampleId, libId = libId), Duration.Inf)
logger.info("Copy Base files")
// Static files that will be copied to the output folder, then file is added to [resourceDir] it's need to be added here also
......@@ -196,14 +194,6 @@ trait ReportBuilder extends ToolCommand {
createDirs = true)
)
logger.info("Parsing summary")
setSummary = SummaryDb.openSqliteSummary(cmdArgs.summaryDbFile)
setRunId = cmdArgs.runId
setSampleCache = Await.result(summary.getSamples(runId = Some(runId)), Duration.Inf).map(r => r.name -> r.id).toMap
setLibraryCache = Await.result(summary.getLibraries(runId = Some(runId)), Duration.Inf).map(r => (setSampleCache.find(_._2 == r.sampleId).get._1, r.name) -> r.id).toMap
setPipelineCache = Await.result(summary.getPipelines(runId = Some(runId)), Duration.Inf).map(r => r.name -> r.id).toMap
setModuleCache = Await.result(summary.getModules(runId = Some(runId)), Duration.Inf).map(r => r.name -> r.id).toMap
total = ReportBuilder.countPages(indexPage)
logger.info(total + " pages to be generated")
......
package nl.lumc.sasc.biopet.utils.implicits
/**
* Created by pjvanthof on 20/02/2017.
*/
object Either {
implicit def optionEitherLeft[T](x: Option[Either[T,_]]): Option[Option[T]] = {
x match {
case Some(i:Either[T, _]) if i.isLeft => Some(i.left.toOption)
case _ => None
}
}
implicit def optionEitherRight[T](x: Option[Either[_,T]]): Option[Option[T]] = {
x match {
case Some(i:Either[_,T]) if i.isRight => Some(i.right.toOption)
case _ => None
}
}
implicit def eitherLeft[T](x: Either[T,_]): Option[T] = {
x match {
case Left(x) => Some(x)
case _ => None
}
}
implicit def eitherRight[T](x: Either[_,T]): Option[T] = {
x match {
case Right(x) => Some(x)
case _ => None
}
}
implicit def left[T](x:T): Left[T, _] = Left(x)
implicit def right[T](x:T): Right[_, T] = Right(x)
implicit def left[T](x:Option[T]): Option[Left[T, _]] = x.map(Left(_))
implicit def right[T](x:Option[T]): Option[Right[_, T]] = x.map(Right(_))
}
package nl.lumc.sasc.biopet.utils.summary.db
import nl.lumc.sasc.biopet.utils.ConfigUtils
import nl.lumc.sasc.biopet.utils.implicits.Either._
import nl.lumc.sasc.biopet.utils.summary.db.Schema._
import slick.driver.H2Driver.api._
......@@ -75,7 +76,7 @@ class SummaryDb(val db: Database) extends Closeable {
getSamples(runId = Some(runId), name = Some(sampleName)).map(_.headOption.map(_.id))
}
/** Return samplId of a specific runId + sampleName */
/** Return sampleName of a specific sampleId */
def getSampleName(sampleId: Int): Future[Option[String]] = {
getSamples(sampleId = Some(sampleId)).map(_.headOption.map(_.name))
}
......@@ -149,6 +150,11 @@ class SummaryDb(val db: Database) extends Closeable {
db.run(q.result)
}
/** Return pipelineId of a specific pipelineName */
def getPipelineId(runId: Int, pipelineName: String): Future[Option[Int]] = {
getPipelines(runId = Some(runId), name = Some(pipelineName)).map(_.headOption.map(_.id))
}
/** Creates a new module, even if it already exist. This may give a database exeption */
def forceCreateModule(name: String, runId: Int, pipelineId: Int): Future[Int] = {
val id = Await.result(db.run(modules.size.result), Duration.Inf)
......@@ -178,6 +184,11 @@ class SummaryDb(val db: Database) extends Closeable {
db.run(q.result)
}
/** Return moduleId of a specific moduleName */
def getmoduleId(runId: Int, moduleName: String, pipelineId: Int): Future[Option[Int]] = {
getModules(runId = Some(runId), name = Some(moduleName), pipelineId = Some(pipelineId)).map(_.headOption.map(_.id))
}
/** Create a new stat in the database, This method is need checking before */
def createStat(runId: Int, pipelineId: Int, moduleId: Option[Int] = None,
sampleId: Option[Int] = None, libId: Option[Int] = None, content: String): Future[Int] = {
......@@ -187,106 +198,190 @@ class SummaryDb(val db: Database) extends Closeable {
/** This create or update a stat */
def createOrUpdateStat(runId: Int, pipelineId: Int, moduleId: Option[Int] = None,
sampleId: Option[Int] = None, libId: Option[Int] = None, content: String): Future[Int] = {
val filter = statsFilter(Some(runId), Some(pipelineId), Some(moduleId), Some(sampleId), Some(libId))
val filter = statsFilter(Some(runId), Some(Left(pipelineId)), Some(Left(moduleId)), Some(Left(sampleId)), Some(Left(libId)))
val r = Await.result(db.run(filter.size.result), Duration.Inf)
if (r == 0) createStat(runId, pipelineId, moduleId, sampleId, libId, content)
else db.run(filter.map(_.content).update(content))
}
/** Return a Query for [[Stats]] */
def statsFilter(runId: Option[Int] = None, pipelineId: Option[Int] = None, moduleId: Option[Option[Int]] = None,
sampleId: Option[Option[Int]] = None, libId: Option[Option[Int]] = None,
def statsFilter(runId: Option[Int] = None, pipeline: Option[Either[Int, String]] = None, module: Option[Option[Either[Int, String]]] = None,
sample: Option[Option[Either[Int, String]]] = None, lib: Option[Option[Either[Int, String]]] = None,
mustHaveSample: Boolean = false, mustHaveLibrary:Boolean = false) = {
var f: Query[Stats, Stats#TableElementType, Seq] = stats
runId.foreach(r => f = f.filter(_.runId === r))
pipelineId.foreach(r => f = f.filter(_.pipelineId === r))
moduleId.foreach(r => f = if (r.isDefined) f.filter(_.moduleId === r.get) else f.filter(_.moduleId.isEmpty))
sampleId.foreach(r => f = if (r.isDefined) f.filter(_.sampleId === r.get) else f.filter(_.sampleId.isEmpty))
libId.foreach(r => f = if (r.isDefined) f.filter(_.libraryId === r.get) else f.filter(_.libraryId.isEmpty))
if (mustHaveSample) f = f.filter(_.sampleId.nonEmpty)
if (mustHaveLibrary) f = f.filter(_.libraryId.nonEmpty)
f
}
f = pipeline match {
case Some(Left(id)) => f.filter(_.pipelineId === id)
case Some(Right(name)) => f.join(pipelines).on(_.pipelineId === _.id).filter(_._2.name === name).map(_._1)
case _ => f
}
f = module match {
case Some(Some(Left(id))) => f.filter(_.moduleId === id)
case Some(Some(Right(name))) => f.join(modules).on(_.moduleId === _.id).filter(_._2.name === name).map(_._1)
case Some(None) => f.filter(_.moduleId.isEmpty)
case _ => f
}
f = sample match {
case Some(Some(Left(id))) => f.filter(_.sampleId === id)
case Some(Some(Right(name))) => f.join(samples).on(_.sampleId === _.id).filter(_._2.name === name).map(_._1)
case Some(None) => f.filter(_.sampleId.isEmpty)
case _ => f
}
f = module match {
case Some(Some(Left(id))) => f.filter(_.libraryId === id)
case Some(Some(Right(name))) => f.join(libraries).on(_.libraryId === _.id).filter(_._2.name === name).map(_._1)
case Some(None) => f.filter(_.libraryId.isEmpty)
case _ => f
}
def statsJoinFilter(runId: Option[Int] = None, pipelineName: Option[String] = None, moduleName: Option[Option[String]] = None,
sampleName: Option[Option[String]] = None, libraryName: Option[Option[String]] = None,
mustHaveSample: Boolean = false, mustHaveLibrary:Boolean = false) = {
var f: Query[Stats, Stats#TableElementType, Seq] = stats
if (runId.isDefined) f = f.filter(_.runId === runId.get)
if (pipelineName.isDefined) f = f.join(pipelines).on(_.pipelineId === _.id).filter(_._2.name === pipelineName.get).map(_._1)
moduleName.foreach(r => if (r.isDefined) f = f.join(modules).on(_.moduleId === _.id).filter(_._2.name === r.get).map(_._1) else f = f.filter(_.moduleId.isEmpty))
sampleName.foreach(r => if (r.isDefined) f = f.join(samples).on(_.sampleId === _.id).filter(_._2.name === r.get).map(_._1) else f = f.filter(_.sampleId.isEmpty))
libraryName.foreach(r => if (r.isDefined) f = f.join(libraries).on(_.libraryId === _.id).filter(_._2.name === r.get).map(_._1) else f = f.filter(_.libraryId.isEmpty))
if (mustHaveSample) f = f.filter(_.sampleId.nonEmpty)
if (mustHaveLibrary) f = f.filter(_.libraryId.nonEmpty)
f
}
/** Return all stats that match given criteria */
def getStats(runId: Option[Int] = None, pipelineId: Option[Int] = None, moduleId: Option[Option[Int]] = None,
sampleId: Option[Option[Int]] = None, libId: Option[Option[Int]] = None,
def getStats(runId: Option[Int] = None, pipeline: Option[Either[Int, String]] = None, module: Option[Option[Either[Int, String]]] = None,
sample: Option[Option[Either[Int, String]]] = None, lib: Option[Option[Either[Int, String]]] = None,
mustHaveSample: Boolean = false, mustHaveLibrary:Boolean = false): Future[Seq[Stat]] = {
db.run(statsFilter(runId, pipelineId, moduleId, sampleId, libId, mustHaveSample, mustHaveLibrary).result)
db.run(statsFilter(runId, pipeline, module, sample, lib, mustHaveSample, mustHaveLibrary).result)
}
/** Return number of results */
def getStatsSize(runId: Option[Int] = None, pipelineName: Option[String] = None, moduleName: Option[Option[String]] = None,
sampleName: Option[Option[String]] = None, libName: Option[Option[String]] = None,
def getStatsSize(runId: Option[Int] = None, pipeline: Option[Either[Int, String]] = None, module: Option[Option[Either[Int, String]]] = None,
sample: Option[Option[Either[Int, String]]] = None, library: Option[Option[Either[Int, String]]] = None,
mustHaveSample: Boolean = false, mustHaveLibrary:Boolean = false): Future[Int] = {
db.run(statsJoinFilter(runId, pipelineName, moduleName, sampleName, libName, mustHaveSample, mustHaveLibrary).size.result)
db.run(statsFilter(runId, pipeline, module, sample, library, mustHaveSample, mustHaveLibrary).size.result)
}
/** Get a single stat as [[Map[String, Any]] */
def getStat(runId: Int, pipelineId: Int, moduleId: Option[Int] = None,
sampleId: Option[Int] =