ReportBuilder.scala 5.15 KB
Newer Older
1
2
3
package nl.lumc.sasc.biopet.core.report

import java.io.{ PrintWriter, File }
4
import java.net.URL
5

6
import nl.lumc.sasc.biopet.core.{ BiopetJavaCommandLineFunction, ToolCommand }
7
import nl.lumc.sasc.biopet.core.summary.Summary
8
import org.broadinstitute.gatk.utils.commandline.Input
9
import org.fusesource.scalate.{ TemplateSource, TemplateEngine }
10
11
12
13
14
15

import scala.io.Source

/**
 * Created by pjvan_thof on 3/27/15.
 */
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
trait ReportBuilderExtension extends BiopetJavaCommandLineFunction {

  val builder: ReportBuilder

  @Input(required = true)
  var summaryFile: File = _

  var outputDir: File = _

  var args: Map[String, String] = Map()

  override def beforeGraph: Unit = {
    super.beforeGraph
    jobOutputFile = new File(outputDir, ".report.log.out")
    javaMainClass = builder.getClass.getName.takeWhile(_ != '$')
  }

  override def commandLine: String = {
    super.commandLine +
      required("--summary", summaryFile) +
      required("--outputDir", outputDir) +
      args.map(x => required(x._1, x._2)).mkString
  }
}

41
42
trait ReportBuilder extends ToolCommand {

43
  case class Args(summary: File = null, outputDir: File = null, pageArgs: Map[String, String] = Map()) extends AbstractArgs
44
45

  class OptParser extends AbstractOptParser {
46
    opt[File]('s', "summary") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
47
48
      c.copy(summary = x)
    }
49
    opt[File]('o', "outputDir") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
50
51
      c.copy(outputDir = x)
    }
52
53
54
    opt[Map[String, String]]('a', "args") action { (x, c) =>
      c.copy(pageArgs = c.pageArgs ++ x)
    }
55
56
57
58
59
60
61
62
  }

  private var setSummary: Summary = _

  final def summary = setSummary

  def pageArgs: Map[String, Any] = Map()

Peter van 't Hof's avatar
Peter van 't Hof committed
63
64
65
  private var done = 0
  private var total = 0

66
67
68
69
70
71
72
73
74
  def main(args: Array[String]): Unit = {
    logger.info("Start")

    val argsParser = new OptParser
    val cmdArgs: Args = argsParser.parse(args, Args()) getOrElse sys.exit(1)

    require(cmdArgs.outputDir.exists(), "Output dir does not exist")
    require(cmdArgs.outputDir.isDirectory, "Output dir is not a directory")

Peter van 't Hof's avatar
Peter van 't Hof committed
75
    logger.info("Write Base files")
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

    /**
     * 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()
        }
      }
    }
114

Peter van 't Hof's avatar
Peter van 't Hof committed
115
    logger.info("Parsing summary")
116
117
    setSummary = new Summary(cmdArgs.summary)

Peter van 't Hof's avatar
Peter van 't Hof committed
118
119
120
    total = countPages(indexPage)
    logger.info(total + " pages to be generated")

Peter van 't Hof's avatar
Peter van 't Hof committed
121
    logger.info("Generate pages")
122
    generatePage(summary, indexPage, cmdArgs.outputDir,
123
124
      args = pageArgs ++ cmdArgs.pageArgs ++
        Map("summary" -> summary, "reportName" -> reportName, "indexPage" -> indexPage))
125

Peter van 't Hof's avatar
Peter van 't Hof committed
126
    logger.info(done + " Done")
127
128
129
130
131
132
  }

  def indexPage: ReportPage

  def reportName: String

Peter van 't Hof's avatar
Peter van 't Hof committed
133
134
135
136
  def countPages(page: ReportPage): Int = {
    page.subPages.map(x => countPages(x._2)).fold(1)(_ + _)
  }

137
138
139
140
141
142
  def generatePage(summary: Summary,
                   page: ReportPage,
                   outputDir: File,
                   path: List[String] = Nil,
                   args: Map[String, Any] = Map()): Unit = {

Peter van 't Hof's avatar
Peter van 't Hof committed
143
144
    val pageOutputDir = new File(outputDir, path.mkString(File.separator))
    pageOutputDir.mkdirs()
145
146
147
148
149
150
151
    val rootPath = "./" + Array.fill(path.size)("../").mkString("")
    val pageArgs = args ++ page.args ++
      Map("page" -> page,
        "path" -> path,
        "outputDir" -> pageOutputDir,
        "rootPath" -> rootPath
      )
152

Peter van 't Hof's avatar
Peter van 't Hof committed
153
154
155
156
    val output = ReportBuilder.renderTemplate("/nl/lumc/sasc/biopet/core/report/main.ssp",
      pageArgs ++ Map("args" -> pageArgs))

    val file = new File(pageOutputDir, "index.html")
157
158
159
160
161
    val writer = new PrintWriter(file)
    writer.println(output)
    writer.close()

    // Generating subpages
162
    for ((name, subPage) <- page.subPages.par) {
163
164
      generatePage(summary, subPage, outputDir, path ::: name :: Nil, pageArgs)
    }
Peter van 't Hof's avatar
Peter van 't Hof committed
165
166
    done += 1
    if (done % 100 == 0) logger.info(done + " Done, " + (done.toDouble / total * 100) + "%")
167
168
  }
}
Peter van 't Hof's avatar
Peter van 't Hof committed
169
170
171
172
173

object ReportBuilder {

  protected val engine = new TemplateEngine()

174
  def renderTemplate(location: String, args: Map[String, Any]): String = {
175
    engine.layout(TemplateSource.fromFile(getClass.getResource(location).getPath), args)
Peter van 't Hof's avatar
Peter van 't Hof committed
176
177
  }
}