Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Mirrors
biopet.biopet
Commits
ad3013df
Commit
ad3013df
authored
May 19, 2015
by
Wai Yi Leung
Browse files
Theme the biopet report with bootstrap, sortable tables.
parent
17ac2dce
Changes
7
Hide whitespace changes
Inline
Side-by-side
public/bammetrics/src/main/resources/nl/lumc/sasc/biopet/pipelines/bammetrics/alignmentSummary.ssp
View file @
ad3013df
...
...
@@ -21,50 +21,61 @@
#if (showPlot)
#{ BammetricsReport.alignmentSummaryPlot(outputDir, "alignmentSummary", summary, !sampleLevel, sampleId = sampleId) }#
<img src="alignmentSummary.png"><br>
<a href="alignmentSummary.tsv">Tsv file</a>
<div class="panel-body">
<img src="alignmentSummary.png" class="img-responsive" />
</div>
<div class="panel-footer">
<i class="glyphicon glyphicon-file"></i> <a href="alignmentSummary.tsv">tsv file</a>
</div>
#end
#if (showTable)
<table>
<thead><tr>
<th>Sample</th>
#if (!sampleLevel) <th>Library</th> #end
<th>Total</th>
<th>Mapped</th>
<th>(%)</th>
<th>Duplicates</th>
<th>(%)</th>
<th>Insert size</th>
</tr></thead>
<tbody>
#for (sample <- samples.toList.sorted)
#{
val libs = (libId, sampleLevel) match {
<div class="panel-body">
<!-- Table -->
<table class="table sortable-theme-bootstrap" data-sortable>
<thead><tr>
<th>Sample</th>
#if (!sampleLevel) <th>Library</th> #end
<th>Total</th>
<th>Mapped</th>
<th>(%)</th>
<th>Duplicates</th>
<th>(%)</th>
<th>Insert size</th>
</tr></thead>
<tbody>
#for (sample <- samples.toList.sorted)
#{
val libs = (libId, sampleLevel) match {
case (_, true) => List("")
case (Some(libId), _) => List(libId.toString)
case _ => summary.libraries(sample).toList
}
}#
<tr><td rowspan="${libs.size}"><a href="${rootPath}Samples/${sample}/index.html">${sample}</a></td>
#for (libId <- libs)
#if (libs.head != libId) <tr> #end
#if (!sampleLevel) <td><a href="${rootPath}Samples/${sample}/Libraries/${libId}/index.html">${libId}</a></td> #end
#{
val prefixPath = List("samples", sample) ::: (if (libId.isEmpty) Nil else List("libraries", libId)) ::: List("bammetrics", "stats")
val total = summary.getValue((prefixPath ::: List("biopet_flagstat", "All")):_*).getOrElse(0L).asInstanceOf[Long]
val mapped = summary.getValue((prefixPath ::: List("biopet_flagstat", "Mapped")):_*).getOrElse(0L).asInstanceOf[Long]
val duplicates = summary.getValue((prefixPath ::: List("biopet_flagstat", "Duplicates")):_*).getOrElse(0L).asInstanceOf[Long]
val insertsizeMean = summary.getValue((prefixPath ::: List("insert_size_metrics", "mean_insert_size")):_*)
}
}#
<td>${total}</td>
<td>${mapped}</td>
<td>${mapped.toDouble / total * 100}%</td>
<td>${duplicates}</td>
<td>${duplicates.toDouble / total * 100}%</td>
<td>${insertsizeMean}</td>
</tr>
<tr><td rowspan="${libs.size}"><a href="${rootPath}Samples/${sample}/index.html">${sample}</a></td>
#for (libId <- libs)
#if (libs.head != libId) <tr> #end
#if (!sampleLevel) <td><a href="${rootPath}Samples/${sample}/Libraries/${libId}/index.html">${libId}</a></td> #end
#{
val prefixPath = List("samples", sample) ::: (if (libId.isEmpty) Nil else List("libraries", libId)) ::: List("bammetrics", "stats")
val total = summary.getValue((prefixPath ::: List("biopet_flagstat", "All")):_*).getOrElse(0L).asInstanceOf[Long]
val mapped = summary.getValue((prefixPath ::: List("biopet_flagstat", "Mapped")):_*).getOrElse(0L).asInstanceOf[Long]
val duplicates = summary.getValue((prefixPath ::: List("biopet_flagstat", "Duplicates")):_*).getOrElse(0L).asInstanceOf[Long]
val insertsizeMean = summary.getValue((prefixPath ::: List("insert_size_metrics", "mean_insert_size")):_*)
}#
<td>${total}</td>
<td>${mapped}</td>
<td>${mapped.toDouble / total * 100}%</td>
<td>${duplicates}</td>
<td>${duplicates.toDouble / total * 100}%</td>
<td>${insertsizeMean}</td>
</tr>
#end
#end
#end
</tbody>
</table>
</tbody>
</table>
</div>
#end
\ No newline at end of file
public/biopet-framework/src/main/resources/nl/lumc/sasc/biopet/core/report/main.ssp
View file @
ad3013df
...
...
@@ -11,7 +11,10 @@
#{
def createMenu(page: ReportPage, path: List[String] = Nil): String = {
val buffer: StringBuffer = new StringBuffer()
buffer.append("
<ul>
")
if (page.subPages.size > 2){
buffer.append("
<ul
class=
\"dropdown-menu\"
role=
\"menu\"
>
")
}
for (subPage
<-
page.subPages
)
{
val
href:
String =
{
...
...
@@ -23,8 +26,9 @@
buffer.append(createMenu(subPage._2, path ::: subPage._1 :: Nil))
buffer.append("
</li>
")
}
buffer.append("
</ul>
")
if(page.subPages.size > 2) {
buffer.append("
</ul>
\n")
}
buffer.toString
}
...
...
@@ -36,42 +40,107 @@
<html>
<head>
<title>
${reportName}
</title>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"${rootPath}css/biopet.css"
>
</head>
<body>
<!-- <header><h1>${reportName}</h1></header> -->
<nav
id=
"menu"
>
<ul>
#for (t
<-
0
to
path.size
)
<
li
>
#if (t == 0)
<a
href=
"${rootPath}index.html"
>
Home
</a>
${unescape(createMenu(indexPage))}
#else
<a
href=
"${rootPath}${path.slice(0, t).mkString("
","/","/")}
index.html
"
>
${path(t - 1)}
</a>
${unescape(createMenu(getSubPage(path.slice(0, t)), path.slice(0, t)))}
#end
</li>
#end
</ul>
<nav
class=
"navbar navbar-inverse navbar-fixed-top"
>
<div
class=
"container"
>
<div
class=
"navbar-header"
>
<button
type=
"button"
class=
"navbar-toggle collapsed"
data-toggle=
"collapse"
data-target=
"#navbar"
aria-expanded=
"false"
aria-controls=
"navbar"
>
<span
class=
"sr-only"
>
Toggle navigation
</span>
<span
class=
"icon-bar"
></span>
<span
class=
"icon-bar"
></span>
<span
class=
"icon-bar"
></span>
</button>
<a
class=
"navbar-brand"
href=
"${rootPath}index.html"
>
Biopet report
</a>
</div>
<div
id=
"navbar"
class=
"collapse navbar-collapse"
>
<ul
class=
"nav navbar-nav"
>
<!-- ${path.size} //-->
<!-- ${path} //-->
#for (t
<-
0
to
path.size
)
#if(t =
=
0)
<
li
>
<a
href=
"${rootPath}index.html"
>
Home
</a>
</li>
${unescape(createMenu(indexPage))}
#else
<!-- sub from the page, should only fetch last item in list
<a href="${rootPath}${path.slice(0,t).mkString("", "/", "/")}index.html">${path( t - 1 )}</a>
${unescape(createMenu(getSubPage(path.slice(0, t)), path.slice(0, t)))}
//-->
#end
#end
</ul>
</div>
<!--/.nav-collapse -->
</div>
</nav>
<aside
id=
"index"
>
<ul>
#for ((name, url)
<-
page.sections
)
<
li
><a
href=
"#${name}"
>
${name}
</a></li>
#end
</ul>
</aside>
<aside
id=
"main"
>
#for ((name, url)
<-
page.sections
)
<
section
id=
"${name}"
>
<h3>
${name}
</h3>
${unescape(url.render(args))}
</section>
#end
</aside>
<footer>
Footer
</footer>
<div
class=
"container-fluid"
>
<div
class=
"row"
>
<div
class=
"col-sm-3 col-md-2 sidebar"
>
<ul
class=
"nav nav-sidebar"
>
<li
class=
"active"
>
<a
href=
"./index.html"
>
Home
</a>
</li>
#for ((name, url)
<-
page.sections
)
<
li
><a
href=
"#${name}"
>
${name}
</a></li>
#end
</ul>
</div>
<div
class=
"col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"
>
#for ((name, url)
<-
page.sections
)
<
a
id=
"${name}"
></a>
<div
class=
"panel panel-primary"
>
<div
class=
"panel-heading"
>
<h3
class=
"panel-title"
id=
"panel-title"
>
${name}
</h3>
</div>
${unescape(url.render(args))}
</div>
<section
id=
"${name}"
>
</section>
#end
</div>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script
src=
"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"
></script>
<!-- Latest compiled and minified CSS -->
<link
rel=
"stylesheet"
href=
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"
>
<!-- Optional theme -->
<link
rel=
"stylesheet"
href=
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css"
>
<!-- Latest compiled and minified JavaScript -->
<script
src=
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"
></script>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"${rootPath}ext/css/bootstrap_dashboard.css"
>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"${rootPath}ext/css/sortable-theme-bootstrap.css"
>
<!-- sortable tables //-->
<script
src=
"${rootPath}ext/js/sortable.min.js"
></script>
<script
language=
"JavaScript"
>
<!--
$
(
document
).
ready
(
function
()
{
Sortable
.
init
()
});
//-->
</script>
</body>
</html>
\ No newline at end of file
public/biopet-framework/src/main/resources/nl/lumc/sasc/biopet/core/report/samplesList.ssp
View file @
ad3013df
...
...
@@ -2,11 +2,11 @@
#import(nl.lumc.sasc.biopet.core.report.ReportPage)
<%@ var summary: Summary %>
<%@ var rootPath: String %>
<table>
<thead><tr></tr><th>Sample</th></thead></tr>
<tbody>
#for (sample <- summary.samples)
<tr><td><a href="${rootPath}Samples/${sample}/index.html">${sample}</a></td></tr>
#end
</tbody>
<table
class="table sortable-theme-bootstrap" data-sortable
>
<thead><tr></tr><th>Sample</th></thead></tr>
<tbody>
#for (sample <- summary.samples)
<tr><td><a href="${rootPath}Samples/${sample}/index.html">${sample}</a></td></tr>
#end
</tbody>
</table>
\ No newline at end of file
public/biopet-framework/src/main/scala/nl/lumc/sasc/biopet/core/report/ReportBuilder.scala
View file @
ad3013df
package
nl.lumc.sasc.biopet.core.report
import
java.io.
{
PrintWriter
,
File
}
import
java.net.URL
import
nl.lumc.sasc.biopet.core.
{
BiopetJavaCommandLineFunction
,
ToolCommand
}
import
nl.lumc.sasc.biopet.core.summary.Summary
...
...
@@ -72,12 +73,44 @@ trait ReportBuilder extends ToolCommand {
require
(
cmdArgs
.
outputDir
.
isDirectory
,
"Output dir is not a directory"
)
logger
.
info
(
"Write Base files"
)
// Write css to output dir
val
cssDir
=
new
File
(
cmdArgs
.
outputDir
,
"css"
)
cssDir
.
mkdirs
()
val
cssWriter
=
new
PrintWriter
(
new
File
(
cssDir
,
"biopet.css"
))
Source
.
fromInputStream
(
getClass
.
getResourceAsStream
(
"/nl/lumc/sasc/biopet/core/report/biopet.css"
)).
getLines
().
foreach
(
cssWriter
.
println
)
cssWriter
.
close
()
/**
* Copying out the static files from this
* */
val
resourcePath
:
String
=
"/nl/lumc/sasc/biopet/core/report/ext/"
val
externalDir
=
new
File
(
cmdArgs
.
outputDir
,
"ext"
)
externalDir
.
mkdirs
()
val
uri
:
URL
=
getClass
.
getResource
(
resourcePath
)
val
dir
:
File
=
new
File
(
uri
.
toURI
)
for
(
srcFile
<-
dir
.
listFiles
)
{
logger
.
info
(
srcFile
.
getPath
)
if
(
srcFile
.
isDirectory
)
{
var
newPath
:
String
=
srcFile
.
getAbsolutePath
.
split
(
resourcePath
).
last
val
workDir
=
new
File
(
externalDir
,
newPath
)
workDir
.
mkdirs
()
logger
.
info
(
"Writing to "
+
workDir
.
getAbsolutePath
)
for
(
f
<-
srcFile
.
listFiles
())
{
var
newFilePath
:
String
=
f
.
getAbsolutePath
.
split
(
resourcePath
+
newPath
).
last
val
resourceWriter
=
new
PrintWriter
(
new
File
(
workDir
,
newFilePath
)
)
val
resourceSrcPath
:
String
=
new
File
(
resourcePath
,
newPath
+
"/"
+
newFilePath
).
getAbsolutePath
Source
.
fromInputStream
(
getClass
.
getResourceAsStream
(
resourceSrcPath
)
).
getLines
().
foreach
(
resourceWriter
.
println
)
resourceWriter
.
close
()
}
}
}
logger
.
info
(
"Parsing summary"
)
setSummary
=
new
Summary
(
cmdArgs
.
summary
)
...
...
public/flexiprep/src/main/resources/nl/lumc/sasc/biopet/pipelines/flexiprep/flexiprepBaseSummary.ssp
View file @
ad3013df
...
...
@@ -20,58 +20,72 @@
FlexiprepReport.baseSummaryPlot(outputDir, "QC_Bases_R1","R1", summary, sampleId = sampleId)
FlexiprepReport.baseSummaryPlot(outputDir, "QC_Bases_R2","R2", summary, sampleId = sampleId)
}#
<table>
<tr><th>R1</th><th>R2</th></tr>
<tr>
<td><img src="QC_Bases_R1.png"><br><a href="QC_Bases_R1.tsv">Tsv file</a></td>
<td><img src="QC_Bases_R2.png"><br><a href="QC_Bases_R2.tsv">Tsv file</a></td>
</tr>
</table>
<div class="panel-body">
<div class="row">
<div class="col-sm-6 col-md-6">
<img src="QC_Bases_R1.png" class="img-responsive" />
</div>
<div class="col-sm-6 col-md-6">
<img src="QC_Bases_R2.png" class="img-responsive" />
</div>
</div>
</div>
<div class="panel-footer">
<i class="glyphicon glyphicon-file"></i> <a href="QC_Bases_R1.tsv">R1 reads stats</a> -
<i class="glyphicon glyphicon-file"></i> <a href="QC_Bases_R2.tsv">R2 reads stats</a>
</div>
#end
#if (showTable)
<table>
<thead><tr>
<th>Sample</th>
<th colspan="2">Library</th>
<th>Before QC</th>
<th>Discarded</th>
<th>(%)</th>
<th>After QC</th>
</tr></thead>
<tbody>
#for (sample <- samples.toList.sorted)
#{
val libs = libId match {
case Some(libId) => List(libId.toString)
case _ => summary.libraries(sample).toList
}
<div class="panel-body">
<!-- Table -->
<table class="table sortable-theme-bootstrap" data-sortable>
val sampleRowspan = {
libs.size +
libs.count(summary.getLibraryValue(sample, _, "flexiprep", "settings", "paired").getOrElse(false) == true)
}
}#
<tr><td rowspan="${sampleRowspan}"><a href="${rootPath}Samples/${sample}/index.html">${sample}</a></td>
#for (libId <- libs)
#if (libs.head != libId) <tr> #end
#{ val paired = summary.getLibraryValue(sample, libId, "flexiprep", "settings", "paired").getOrElse(false) }#
<td #if (paired == true) rowspan="2" #end><a href="${rootPath}Samples/${sample}/Libraries/${libId}/index.html">${libId}</a></td>
#{ val reads = if (paired == true) List("R1", "R2") else List("R1") }#
#for (read <- reads)
#if (read == "R2") </tr><tr> #end
#{
val beforeTotal = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "seqstat_" + read, "bases", "num_total").getOrElse(0).asInstanceOf[Long]
val afterTotal = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "seqstat_" + read + "_after", "bases", "num_total").getOrElse(0).asInstanceOf[Long]
}#
<td>${read}</td>
<td>${beforeTotal}</td>
<td>${beforeTotal - afterTotal}</td>
<td>${(beforeTotal - afterTotal).toDouble / beforeTotal * 100}%</td>
<td>${afterTotal}</td>
<thead><tr>
<th>Sample</th>
<th colspan="2">Library</th>
<th>Before QC</th>
<th>Discarded</th>
<th>(%)</th>
<th>After QC</th>
</tr></thead>
<tbody>
#for (sample <- samples.toList.sorted)
#{
val libs = libId match {
case Some(libId) => List(libId.toString)
case _ => summary.libraries(sample).toList
}
val sampleRowspan = {
libs.size +
libs.count(summary.getLibraryValue(sample, _, "flexiprep", "settings", "paired").getOrElse(false) == true)
}
}#
<tr><td rowspan="${sampleRowspan}"><a href="${rootPath}Samples/${sample}/index.html">${sample}</a></td>
#for (libId <- libs)
#if (libs.head != libId) <tr> #end
#{ val paired = summary.getLibraryValue(sample, libId, "flexiprep", "settings", "paired").getOrElse(false) }#
<td #if (paired == true) rowspan="2" #end><a href="${rootPath}Samples/${sample}/Libraries/${libId}/index.html">${libId}</a></td>
#{ val reads = if (paired == true) List("R1", "R2") else List("R1") }#
#for (read <- reads)
#if (read == "R2") </tr><tr> #end
#{
val beforeTotal = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "seqstat_" + read, "bases", "num_total").getOrElse(0).asInstanceOf[Long]
val afterTotal = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "seqstat_" + read + "_after", "bases", "num_total").getOrElse(0).asInstanceOf[Long]
}#
<td>${read}</td>
<td>${beforeTotal}</td>
<td>${beforeTotal - afterTotal}</td>
<td>${(beforeTotal - afterTotal).toDouble / beforeTotal * 100}%</td>
<td>${afterTotal}</td>
#end
</tr>
#end
#end
</tr>
#end
#end
</tbody>
</table>
</tbody>
</table>
</div>
#end
\ No newline at end of file
public/flexiprep/src/main/resources/nl/lumc/sasc/biopet/pipelines/flexiprep/flexiprepReadSummary.ssp
View file @
ad3013df
...
...
@@ -21,60 +21,74 @@
FlexiprepReport.readSummaryPlot(outputDir, "QC_Reads_R1","R1", summary, sampleId = sampleId)
FlexiprepReport.readSummaryPlot(outputDir, "QC_Reads_R2","R2", summary, sampleId = sampleId)
}#
<table>
<tr><th>R1</th><th>R2</th></tr>
<tr>
<td><img src="QC_Reads_R1.png"><br><a href="QC_Reads_R1.tsv">Tsv file</a></td>
<td><img src="QC_Reads_R2.png"><br><a href="QC_Reads_R2.tsv">Tsv file</a></td>
</tr>
</table>
<div class="panel-body">
<div class="row">
<div class="col-sm-6 col-md-6">
<img src="QC_Reads_R1.png" class="img-responsive">
</div>
<div class="col-sm-6 col-md-6">
<img src="QC_Reads_R2.png" class="img-responsive">
</div>
</div>
</div>
<div class="panel-footer">
<i class="glyphicon glyphicon-file"></i> <a href="QC_Reads_R1.tsv">R1 reads stats</a> -
<i class="glyphicon glyphicon-file"></i> <a href="QC_Reads_R2.tsv">R2 reads stats</a>
</div>
#end
#if (showTable)
<table>
<thead><tr>
<th>Sample</th>
<th colspan="2">Library</th>
<th>Before QC</th>
<th>Clipping</th>
<th>Trimming</th>
<th>After QC</th>
</tr></thead>
<tbody>
#for (sample <- samples.toList.sorted)
#{
val libs = libId match {
case Some(libId) => List(libId.toString)
case _ => summary.libraries(sample).toList
}
val sampleRowspan = {
libs.size +
libs.count(summary.getLibraryValue(sample, _, "flexiprep", "settings", "paired").getOrElse(false) == true)
}
}#
<tr><td rowspan="${sampleRowspan}"><a href="${rootPath}Samples/${sample}/index.html">${sample}</a></td>
#for (libId <- libs)
#if (libs.head != libId) <tr> #end
#{ val paired = summary.getLibraryValue(sample, libId, "flexiprep", "settings", "paired").getOrElse(false) }#
<td #if (paired == true) rowspan="2" #end><a href="${rootPath}Samples/${sample}/Libraries/${libId}/index.html">${libId}</a></td>
#{ val reads = if (paired == true) List("R1", "R2") else List("R1") }#
#for (read <- reads)
#if (read == "R2") </tr><tr> #end
<div class="panel-body">
<!-- Table -->
<table class="table sortable-theme-bootstrap" data-sortable>
<thead><tr>
<th>Sample</th>
<th colspan="2">Library</th>
<th>Before QC</th>
<th>Clipping</th>
<th>Trimming</th>
<th>After QC</th>
</tr></thead>
<tbody>
#for (sample <- samples.toList.sorted)
#{
val beforeTotal = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "seqstat_" + read, "reads", "num_total")
val afterTotal = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "seqstat_" + read + "_after", "reads", "num_total")
val clippingDiscardedToShort = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "clipping_" + read, "num_reads_discarded_too_short").getOrElse(0).asInstanceOf[Long]
val clippingDiscardedToLong = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "clipping_" + read, "num_reads_discarded_too_long").getOrElse(0).asInstanceOf[Long]
val trimmingDiscarded = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "trimming", "num_reads_discarded_" + read).getOrElse(0).asInstanceOf[Long]
val libs = libId match {
case Some(libId) => List(libId.toString)
case _ => summary.libraries(sample).toList
}
val sampleRowspan = {
libs.size +
libs.count(summary.getLibraryValue(sample, _, "flexiprep", "settings", "paired").getOrElse(false) == true)
}
}#
<td>${read}</td>
<td>${beforeTotal}</td>
<td>${clippingDiscardedToShort + clippingDiscardedToLong}</td>
<td>${trimmingDiscarded}</td>
<td>${afterTotal}</td>
<tr><td rowspan="${sampleRowspan}"><a href="${rootPath}Samples/${sample}/index.html">${sample}</a></td>
#for (libId <- libs)
#if (libs.head != libId) <tr> #end
#{ val paired = summary.getLibraryValue(sample, libId, "flexiprep", "settings", "paired").getOrElse(false) }#
<td #if (paired == true) rowspan="2" #end><a href="${rootPath}Samples/${sample}/Libraries/${libId}/index.html">${libId}</a></td>
#{ val reads = if (paired == true) List("R1", "R2") else List("R1") }#
#for (read <- reads)
#if (read == "R2") </tr><tr> #end
#{
val beforeTotal = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "seqstat_" + read, "reads", "num_total")
val afterTotal = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "seqstat_" + read + "_after", "reads", "num_total")
val clippingDiscardedToShort = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "clipping_" + read, "num_reads_discarded_too_short").getOrElse(0).asInstanceOf[Long]
val clippingDiscardedToLong = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "clipping_" + read, "num_reads_discarded_too_long").getOrElse(0).asInstanceOf[Long]
val trimmingDiscarded = summary.getLibraryValue(sample, libId, "flexiprep", "stats", "trimming", "num_reads_discarded_" + read).getOrElse(0).asInstanceOf[Long]
}#
<td>${read}</td>
<td>${beforeTotal}</td>
<td>${clippingDiscardedToShort + clippingDiscardedToLong}</td>
<td>${trimmingDiscarded}</td>
<td>${afterTotal}</td>
#end
</tr>
#end
#end
</tr
>
#end
#end